NVAPI Reference Manual

NV API

Welcome

Thanks for using the NV API.

Using The Documentation

Click to go to the main document page. Scroll down a bit and look for the sections that have been labelled and grouped together. For example, The Members heading shows a list of all the routes available for members for you to use.

Members

Clicking members will guide you on getting all of the information for all Members.

If you are looking for a single member, pass their member id. Some member IDs do have a - in them: e.g., 12341234-01

You can find members by Association, and Family.

Memberships

Clicking memberships will guide you on getting all of the information for all Memberships.

If you are looking for a single membership, pass their membership id.

You will also be able to find memberships by Association, Branch and Membership Category.

Receipts

In order to Add a receipt use POST with the applicable paramaters.

To mark a receipt as Paid, use PUT and the applicable params needed depending on if it was a Credit Card Checkout; a Express Checkout or an e-Pay Checkout.

Copyright

Copyright (c) 2013 NetVenturesCorporation.

Top Level Namespace

Defined Under Namespace

Classes: App

Class: App

Inherits:
Sinatra::Base
  • Object
show all
Defined in:
app/main.rb,
app/routes/sso.rb,
app/routes/scans.rb,
app/routes/camps.rb,
app/routes/emails.rb,
app/routes/status.rb,
app/routes/pickups.rb,
app/routes/pledges.rb,
app/routes/seasons.rb,
app/routes/options.rb,
app/routes/members.rb,
app/routes/appeals.rb,
app/routes/waivers.rb,
app/routes/credits.rb,
app/routes/classes.rb,
app/routes/invoices.rb,
app/routes/accounts.rb,
app/routes/programs.rb,
app/routes/receipts.rb,
app/routes/families.rb,
app/routes/branches.rb,
app/routes/subsidies.rb,
app/routes/campaigns.rb,
app/routes/bus_infos.rb,
app/routes/schedules.rb,
app/routes/gift_cards.rb,
app/routes/childcares.rb,
app/routes/categories.rb,
app/routes/memberships.rb,
app/routes/associations.rb,
app/routes/allergy_info.rb,
app/routes/transactions.rb,
app/routes/authenticate.rb,
app/routes/user_masters.rb,
app/routes/corporations.rb,
app/routes/cache_status.rb,
app/routes/immunizations.rb,
app/routes/camp_sessions.rb,
app/routes/member_images.rb,
app/routes/counter_items.rb,
app/routes/questionnaires.rb,
app/routes/donation_prompt.rb,
app/routes/medical_contacts.rb,
app/routes/pending_receipts.rb,
app/routes/program_sessions.rb,
app/routes/security_settings.rb,
app/routes/emergency_contacts.rb,
app/routes/payment_instruments.rb,
app/routes/membership_categories.rb,
app/routes/enrollment_priorities.rb

SSO (collapse)

Scans (collapse)

Emails (collapse)

Pickup (collapse)

Members (collapse)

Classes GET route for Lists all classes. Optionally returns only classes for a given program or session. (collapse)

Programs (collapse)

Receipts (collapse)

BusInfo (collapse)

GiftCards (collapse)

Memberships (collapse)

Associations (collapse)

AllergyInfo (collapse)

UserMaster (collapse)

Corporations (collapse)

Immunization (collapse)

Questionnaire (collapse)

MedicalContact (collapse)

PendingReceipts (collapse)

EmergencyContact (collapse)

Instance Method Summary (collapse)

Instance Method Details

- (JSON) authenticate

POST route to create an SSO token for a [UserMaster] user/password

Parameters:

  • client_id

    is the Client ID of the caller requesting access to the SSO system

  • client_secret

    is the Client Secret of the caller requesting access to the SSO system

  • username

    the UserMaster.UserId of the user to authenticate

  • password

Returns:

  • (JSON)

    with sso_token on success



11
12
13
14
15
16
17
18
# File 'app/routes/sso.rb', line 11

post %r{^/v#{settings.version}/\d+/sso/authenticate(\?.*)?$} do
  halt_with_error(403, "Not authorized to use the SSO System") unless SsoGate.client_authorized?(params["client_id"], params["client_secret"])

  token = SsoGate.authenticate_user_and_return_token(params["username"], params["password"])
  halt_with_error(403, "Username or password invalid") unless token

  render_json({:sso_token => token})
end

- (Object) get("/<api version>/<association id>/authenticate")

Performs association api authentication. This authentication token allows read/write access to all records in one specific association.

Query Parameters

  • api_key: api key to authenticate against


35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'app/routes/authenticate.rb', line 35

get %r{^/v#{settings.version}/\d+/authenticate$} do
  k = ApiKey.where(:key => params[:api_key]).first
  if k && k.class == AssociationKey && k.association_id == @association.db.id
    sesh = Session.new(owner_id: @association.db.id, type: :association)
    sesh.token = SecureRandom.uuid
    if sesh.store
      headers 'X-Authentication-Token' => sesh.token
      case request.preferred_type(['text/html', 'application/json'])
      when /json/
        render_json({:result => 'success', :authentication_token => sesh.token})
      when /html/
        session[:authentication_token] = sesh.token
        redirect "/v#{settings.version}/#{@association.db.id}"
      else halt 200
      end
    else
      authentication_failure
    end
  else
    authentication_failure
  end
end

- (Object) get("/<api version>/<association id>/families/authenticate")

Verifies a login/password combination.

Query Parameters

  • login: the login to test
  • password: the password to test


98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'app/routes/authenticate.rb', line 98

get %r{^/v#{settings.version}/\d+/(family_connections|families)/authenticate(\?.*)?$} do
  unless params[:login] && params[:password]
    authentication_failure
  end

  family = @families.where(:FC_LoginID => params[:login]).first

  if family && family.authenticate(params[:password])
    session[:family] = family.id
    family.flush_temporary_transactions(@association.pay_pal_configuration) #what if it can't be flushed or shouldn't be
    render_json({:result => :success}, {:family => {:id => family.id}})
  else
    authentication_failure
  end
end

- (Object) get("/<api version>/authenticate")

Performs global api authentication. This authentication token allows read/write access to all records in all associations.

Query Parameters

  • api_key: api key to authenticate against


66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'app/routes/authenticate.rb', line 66

get %r{^/v#{settings.version}/authenticate$} do

  k = ApiKey.where(:key => params[:api_key]).first
  if k && k.class == GlobalKey
    sesh = Session.new(type: :global)
    sesh.token = SecureRandom.uuid
    if sesh.store
      headers 'X-Authentication-Token' => sesh.token
      case request.preferred_type(['text/html', 'application/json'])
      when /json/
        render_json({:result => 'success', :authentication_token => sesh.token})
      when /html/
        session[:authentication_token] = sesh.token
        halt 200, haml(:authenticate, :locals => { :token => sesh.token })
      else halt 200
      end
    else
      authentication_failure
    end
  else
    authentication_failure
  end
end

- (Object) authentication_failure



153
154
155
156
157
158
159
160
# File 'app/routes/authenticate.rb', line 153

def authentication_failure
  case request.preferred_type(['text/html', 'application/json'])
  when /json/
    halt_with_error(401, "Authentication failed")
  else
    halt 401, "Authentication failed"
  end
end

- (Object) current_user



149
150
151
# File 'app/routes/authenticate.rb', line 149

def current_user
  session[:usermaster_id]
end

- (Object) delete_temporary_transactions

Deletes temporary transactions



90
91
92
93
# File 'app/routes/transactions.rb', line 90

delete %r{^/v#{settings.version}/\d+(/families/[^/]+)/transactions/temporary(\?.*)?$} do
  @family.flush_temporary_transactions @association.pay_pal_configuration
  halt 204
end

- (JSON) post("/<api version>/<association id>/families/<family id>/members")

Creates a new member.

Pass all standard fields as returned by the GET method. In order to save custom field values for a member, pass custom fields as:

{ ..., "customFieldValues" : { "<field id>": "<data>", "<field id>": "<data>", ... }, ... }

where:

  • <field id> is the id defined in the customization section of the field definition.
  • <data> is the actual value of the field. Returns a 201 on Success. Returns a 400 if the member information is not valid, or the system couldn't make it a member for some reason. Also, a 500 is returned if the Member object is not created. homePhone workPhone cellPhone emergencyPhone are sanitized to verify it is a proper phonenumber prior to being saved. As is zipcode.

Returns:

  • (JSON)

    of all information regarding the members

See Also:



111
112
113
114
# File 'app/routes/members.rb', line 111

def find_demographic_fields(data)
  potential_demographic_fields = data.keys.select { |k| k =~ /demographics?/i }
  potential_demographic_fields.first
end

- (Object) get(/<api version>/<associationid>/members/<memberid>/allergy_infos/<allergy_infoid>)

Returns the allergy_info record based on it's id and on the member id



46
47
48
49
# File 'app/routes/allergy_info.rb', line 46

get %r{^/v#{settings.version}/\d+/members/[^/]+?/allergy_infos/(\d+)?$} do |the_id|
  @allergy_info = AllergyInfo.where(:cc_ALLER_id => the_id).first
  render_show(@allergy_info)
end

- (Object) get(/<api version>/<associationid>/members/<memberid>/allergy_infos)

before %r/members/([\w-]+) do |id| # bypass this overload if it's for member images # (which won't have @association based on previous overloads) if @association && id @member = settings.cache.fetch("#App.@association@association.cache_key_member_#id") do Member.find(id) end end end Find out information about a Camp Participant's AllergyInfo

Returns all AllergyInfos for a member id



17
18
19
20
21
# File 'app/routes/allergy_info.rb', line 17

get %r{^/v#{settings.version}/\d+/members/[^/]+?/allergy_infos(\?.*)?$} do
  @allergy_infos = AllergyInfo.where(:cc_ALLER_cc_par => @member.participant.id) #AllergyInfo.execute_procedure(:cc_GetAuthorizedAllergyInfo, @member.participant.id)

  render_index(@allergy_infos, AllergyInfo)
end

- (Object) get("/<api version>/<association id>/appeals/<appeal id>") - (Object) get("/<api version>/<association id>/campaigns/<campaign id>/appeals/<appeal id>")

Describes an appeal.



38
39
40
# File 'app/routes/appeals.rb', line 38

get %r{^/v#{settings.version}/\d+(/campaigns/\d+)?/appeals/\d+(\?.*)?$} do
  render_show @appeal, :links => makelinks(%w[pledges])
end

- (Object) get("/<api version>/<association id>/appeals") - (Object) get("/<api version>/<association id>/campaigns/<campaign id>/appeals")

Lists all appeals. Optionally filters by campaign.

Query parameters

  • active: only show active appeals
  • ssp: only show appeals set for the ssp


27
28
29
30
31
# File 'app/routes/appeals.rb', line 27

get %r{^/v#{settings.version}/\d+(/campaigns/\d+)?/appeals(\?.*)?$} do
  @appeals = @appeals.ssp if params.has_key?('ssp')
  @appeals = @appeals.active if params.has_key?('active')
  render_index @appeals, Appeal
end

- (Object) get("/<api version>/<association id>")

return [JSON] All information about a specific Association or Branch

Parameters:

  • program

    show Custom Fields that have NVC_CF_ProgramEnabled = 1

  • subsidy

    show Custom Fields that have NVC_CF_SubsidyEnabled = 1

  • crm

    show Custom Fields that have NVC_CF_CrmEnabled = 1

  • fundraising

    show Custom fields that have NVC_CF_FundRaisingEnabled = 1



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'app/routes/associations.rb', line 63

get %r{^/v#{settings.version}/\d+(\?.*)?$} do
  customizations = @association.customizations
  extra =
    { :id => @association.db.id,
    :baseUrl => @association.Y_Base_Url,
    :announcements => customizations.Announcements,
    :ePayNotification => customizations.MP_EpayNotification,
    :allowSelfServiceNonMemberEnrollment => customizations.IsNonMemberEnroll == 1,
    :allowVisitorsToCreateAccount => customizations.MP_AllowVisitorsToCreateAccount == 1,
    :allowToCreateMembership => customizations.MP_AllowToCreateMembership == 1,
    :allowMembershipRenewals => customizations.DisableRenewalFromMemberPortal == 0,
    :allowDonations => customizations.MP_MakeDonation == 1,
    :enableSalesTax => customizations.ChargeSalesTax == 1,
    :enableProgramAgeRestrictions => customizations.EnforceMemberPortalAgeRestriction == 1,
    :enableChildcareAgeRestrictions => customizations.CC_EnforceAgeRestriction == 1,
    :enableCampAgeRestrictions => customizations.CC_EnforceAgeRestriction == 1,
    :enableContactInfoForNonMember => customizations.MP_EnableContactInfoForNonMember == 1,
    :waivers => get_waivers(customizations),
    :billDates => customizations.MP_ProratingBillDates.nil? ? nil : customizations.MP_ProratingBillDates.split("|").map {|s| s.to_i},
    :enableProrating => customizations.AllowMembershipProRating == 1,
    :taxId => customizations.taxId,
    :showTaxIdOnReceipt => customizations.taxId_displayOnReceipt == 1,
    :showTaxIdOnPaymentHistory => customizations.TaxID_DisplayOnPaymentHistoryReport == 1,
    :showDonationGraph => customizations.SSP_EnableMyDonationGraph == 1,
    :utcOffset => customizations.TimeZone,
    :acceptedCards => CreditCardType.pluck(:CardVendor),
    :sspSaveEpayForCamp => customizations.MP_SaveEpayForCamps == 1,
    :sspCampEpayNotificationMessage => customizations.MP_Camp_Epay_Notification,
    :allowCampSelfServiceRegistration => customizations.CC_AllowSelfServiceRegistration == 1,
    :isBranchMemerPortalEnabled => @association.db.attributes.keys.include?("isBranchMemerPortalEnabled") ? @association.db.isBranchMemerPortalEnabled : 0,
    :isClientOnHub => @association.isClientUsingHUB,
    :isClientUsingHUBMobile => @association.isClientUsingHUBMobile,
    :default_branch => @association.Y_Branch,
    :membershipReceiptingFields => MembershipCustomFieldSection.includes(:fields => [:drop_down => :options, :field => :options]).all.map do |section|
      { :section => api_attributes(section),
        :fields => section.fields.map do |field|
          custom_fields(field, 'MRF').merge!(:customization => custom_fields(field.field, 'NVC'))
        end }
    end,
    :links => makelinks(
                        %w[appeals branches campaigns categories classes corporations counter_items families
           gift_cards invoices members membership_categories memberships
           pledges programs receipts scans program_sessions transactions
           credits seasons camps camp_sessions schedules subsidies]),
    :images => [
                { :content => "Logo",
                  :href => url(settings.images + '/' + @association.Y_PrintImage),
                  :rel => 'logo' },
                {:content => "MobileLogo",
                  :href => url(settings.images + '/' + @association.Y_MobileLogo),
                  :rel => 'mobilelogo'
                }
               ]
  }
  image_names =
    { :header => ['Header Image', @association.Y_MemberPortalHeaderImage],
    :footer => ['Footer Image', @association.Y_MemberPortalFooterImage],
    :generalHeader => ['General Header Image', @association.Y_MemberPortalGeneralHeaderImage],
    :donationHeader => ['Donation Header Image', @association.Y_MemberPortalDonationHeaderImage],
    :membershipHeader => ['Membership Header Image', @association.Y_MemberPortalMembershipHeaderImage],
    :programHeader => ['Program Header Image', @association.Y_MemberPortalProgramHeaderImage],
    :shareHeader => ['Share Header Image', @association.Y_MemberPortalShareHeaderImage] }
  image_names.each do |rel,image|
    if image[1] && !image[1].empty?
      path = "/images/#{@association.db.connection_info[:database]}/#{image[1]}"
      unless File.exists?("./public#{path}")
        unless Dir.exists?(File.dirname("./public#{path}"))
          Dir.mkdir(File.dirname("./public#{path}"))
        end
        File.open("./public#{path}", 'w') do |f|
          f.write(MemberPortalStyle.where(:MPS_ImageName => image[1], :MPS_ClientDb => @association.y_dsn2).first.MPS_Image)
        end
      end
      extra[:images] <<
        { :content => image[0],
        :href => url(path),
        :rel => "#{rel}" }
    end
  end
  social_base = BranchSocialMedia.scoped.where(SM_BranchCode: "-1")
  if social_base.present?
    social = social_base.first
    extra[:socialMedia] =
      {:twitter => social.SM_Twitter.present? ? social.SM_Twitter : @association.twitterAccount,
      :facebook => social.SM_Facebook,
      :pintrest => social.SM_Pinterest,
      :youtube => social.SM_YouTube,
      :vimeo => social.SM_Vimeo,
      :flickr => social.SM_Flickr,
      :instagram => social.SM_Instagram,
      :google_plus => social.SM_GooglePlus}
  end
  (10..11) === DonateNow.first.DN_EnableDonateNow.to_i && extra[:links] <<
    { :content => 'Donate Now',
    :href => @association.Y_DonateNowLink,
    :rel => 'donateNow' }
  DonationPrompt.first.try(:enabled?) && extra[:links] |= makelinks(%w[donation_prompt])
  customizations.IS_Fee_RM == 1 && extra[:memberHeader] = customizations.FEE_RM_Header
  customizations.IS_Fee_NM == 1 && extra[:nonMemberHeader] = customizations.FEE_NM_Header
  customizations.IS_Fee_BM == 1 && extra[:programMemberHeader] = customizations.FEE_BM_Header
  handle_custom_fields(params, extra) if params
  render_show(@association, extra)
end

- (JSON) get("/<api version>")

GET route for information about all Associations then will pass extra information if given the search param.

Lists all associations

Parameters:

  • name

    searches all associations OrganizationName column by the exact value you pass in name

  • search

    searches all associations by City, State, and YName by the fuzzy match of the values you pass (ideal for mobile). Passes extra info like id, address, city, state, phone and images.

Returns:

  • (JSON)

    on success



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'app/routes/associations.rb', line 29

get %r{^/v#{settings.version}$} do
  extras = {}
  if params.has_key?("name")
    @associations = @associations.where(:OrganizationName => params['name'])
    extras = {}
  elsif params.has_key?("search")
    search_params = params[:search].valid_encoding? ? params[:search].gsub(/\W+/, '') : "nothing"
    params[:search] = search_params
    @associations = @associations.where('City like(:term) or State like(:state_term) or YName like(:term)', { :term => "%#{search_params}%", :state_term => search_params })
    @associations = @associations.where('HUBMobileClient = ?', 1) if (params.has_key?("onlyMobileHubEnabled") ||  params.has_key?("onlyMobileEnabled"))
    extras = {
      :organizationName => lambda{|assoc| assoc.OrganizationName},
      :id => lambda{|assoc| assoc.ID },
      :addressOne => lambda{|addy| addy.Address1 },
      :addressTwo => lambda{|addy| addy.Address2 },
      :city => lambda{|citi| citi.City },
      :state => lambda{|state| state.State },
      :zipcode => lambda{|zipc| zipc.ZipCode},
      :on_mobile => lambda{|mob| mob.HUBMobileClient},
      :on_hub => lambda{|hub| hub.HUBClient},
      :phone => lambda { |assoc| assoc.YPhone },
      :images => lambda{ |assoc| [ { :content => "Logo", :href => show_images(assoc), :rel => 'logo' }] }
    }
  end
  render_index(@associations, AssociationDatabase, extras)
end

- (Object) get("/<api version>/<association id>/branches/<branch id>")

Describes a branch.



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'app/routes/branches.rb', line 33

get %r{^/v#{settings.version}/\d+/branches/\d+(\?.*)?$} do
  branch_association = Association.where(:y_ClientCode => @branch.BranchGroupId).first
  social = @branch.social_media
  extra = {
    :address_one => branch_association.Y_Address_1,
    :address_two => branch_association.Y_Address_2,
    :city => branch_association.Y_City,
    :state => branch_association.Y_State,
    :zip_code => branch_association.Y_ZipCode,
    :phone => branch_association.y_phone,
    :links => makelinks(%w[categories counter_items membership_categories memberships programs scans seasons camps classes schedules])
  }
  if social.present?
    extra = extra.merge(
      {:twitter => social.SM_Twitter.present? ? social.SM_Twitter : @association.twitterAccount,
       :facebook => social.SM_Facebook,
       :pintrest => social.SM_Pinterest,
       :youtube => social.SM_YouTube,
       :vimeo => social.SM_Vimeo,
       :flickr => social.SM_Flickr,
       :instagram => social.SM_Instagram,
       :google_plus => social.SM_GooglePlus}
    )
  end
  render_show @branch, extra
end

- (Object) get("/<api version>/<association id>/branches")

Lists all branches.

Query Parameters

  • ssp: only show branches set to display in the ssp
  • valid: only show branches that are valid.


23
24
25
26
27
# File 'app/routes/branches.rb', line 23

get %r{^/v#{settings.version}/\d+/branches(\?.*)?$} do
  @branches = @branches.ssp if params.has_key?('ssp')
  @branches = @branches.valid if params.has_key?('valid')
  render_index @branches, Branch
end

- (Object) get(/<api version>/<associationid>/members/<memberid>/bus_infos/<bus_infoid>)

Returns the bus_info record based on it's id and on the member id



43
44
45
46
# File 'app/routes/bus_infos.rb', line 43

get %r{^/v#{settings.version}/\d+/members/[^/]+?/bus_infos/(\d+)?$} do |the_id|
  @bus_info = BusInfo.where(:cc_BPU_id => the_id).first
  render_show(@bus_info)
end

- (Object) get(/<api version>/<associationid>/members/<memberid>/bus_infos)

before %r/members/([\w-]+) do |id| # bypass this overload if it's for member images # (which won't have @association based on previous overloads) if @association && id @member = settings.cache.fetch("#App.@association@association.cache_key_member_#id") do Member.find(id) end end end Find out information about a Camp Participant's BusInfo

Returns all BusInfos for a member id



17
18
19
20
21
# File 'app/routes/bus_infos.rb', line 17

get %r{^/v#{settings.version}/\d+/members/[^/]+?/bus_infos(\?.*)?$} do
  @bus_infos = BusInfo.where(:cc_BPU_cc_par => @member.participant.id) #BusInfo.execute_procedure(:cc_GetAuthorizedBusInfo, @member.participant.id)

  render_index(@bus_infos, BusInfo)
end

- (Object) get("/<api version>/<association id>/camps/<camp id>") - (Object) get("/<api version>/<association id>/branches/<branch id>/camps/<camp id>") - (Object) get("/<api version>/<association id>/seasons/<season id>/camps/<camp id>")

Describes a camp.



199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'app/routes/camps.rb', line 199

get %r{^/v#{settings.version}/\d+(/branches/\d+)?(/seasons/\d+)?/camps/\d+(\?.*)?$} do
  Camp.preload(@camp.id)
  img = @camp.image(settings.images, settings.servers)
  camp_fields = settings.cache.fetch("#{@association.cache_key}_camp_#{@camp.id}_fields") { @camp.fields }
  extras = { :links => makelinks(%w[camp_sessions schedules enrollment_priorities]),
    :depositEnabledStaff => @camp.deposit_enabled_staff,
    :depositEnabledSSP => @camp.deposit_enabled_ssp,
    :images => img && [
      { :content => "Image",
        :href => url(img),
        :rel => 'image' }]}
  extras[:customFields] = camp_fields.map{|field| custom_fields(field, 'CC')} if [0,2].include? @camp.cc_ProgramEnabled
  render_show(@camp, extras)
end

- (Object) get("/<api version>/<association id>/camp_sessions/<camp session id>") - (Object) get("/<api version>/<association id>/camps/<camp id>/camp_sessions/<camp session id>")

Describes a camp session.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'app/routes/camp_sessions.rb', line 40

get %r{^/v#{settings.version}/\d+((/branches/\d+)?(/seasons/\d+)?/camps/\d+)?/camp_sessions/\d+(\?.*)?$} do
  extra =
    { :links => makelinks(%w[schedules]) }
  extra[:documents] = Array.new
  @camp_session.camp.document_references.each do |document|
    doc = Document.select([:CDM_DocName, :CDM_DocId, :CDM_BranchCode]).find(document.ACD_CDM_DocId)
    extra[:documents] <<
      { :name => doc.CDM_DocName,
        :href => url(Document.doc(doc.CDM_DocId, doc.CDM_DocName, settings.servers)),
        :status => document.ACD_STATUS,
        :branchId => doc.CDM_BranchCode }
  end
  render_show(@camp_session, extra)
end

- (Object) get("/<api version>/<association id>/camp_sessions") - (Object) get("/<api version>/<association id>/camps/<camp id>/camp_sessions")

Lists all camp sessions.

Query Parameters

  • active: search for active camp sessions
  • enabled: search for enabled camp sessions


29
30
31
32
33
# File 'app/routes/camp_sessions.rb', line 29

get %r{^/v#{settings.version}/\d+((/branches/\d+)?(/seasons/\d+)?/camps/\d+)?/camp_sessions(\?.*)?$} do
  @camp_sessions = @camp_sessions.active if params.has_key?('active')
  @camp_sessions = @camp_sessions.enabled if params.has_key?('enabled')
  render_index(@camp_sessions, CampSession)
end

- (Object) get("/<api version>/<association id>/campaigns/<campaign id>")

Describes a campaign.



70
71
72
73
74
75
76
77
78
# File 'app/routes/campaigns.rb', line 70

get %r{^/v#{settings.version}/\d+/campaigns/\d+(\?.*)?$} do
  Campaign.preload(@campaign.id)
  img = @campaign.image(settings.images, settings.servers)
  extra = {}
  extra[:links] = makelinks(%w[appeals])
  extra[:images] =  img && [{ :content => "Image", :href => url(img), :rel => 'image' }]
  extra[:totalPledge] = @campaign.total_pledge
  render_show(@campaign, extra)
end

- (Object) get("/<api version>/<association id>/camps") - (Object) get("/<api version>/<association id>/branches/<branch id>/camps") - (Object) get("/<api version>/<association id>/seasons/<season id>/camps")

Lists all camps. Optionally filters by branch.

Query Parameters

  • keyword: search for camps by keyword
  • age: search for camps available to a given age. Accepts a comma-separated range of ages (such as "4,17") or a single value
  • months: specify to search for age in months, not years
  • active: search for active camps
  • enabled: search for enabled camps
  • ssp: search for ssp-available camps
  • day: show only camps that meet on the given days. Accepts a string contaning a combination of the following letters (any order is valid):
    • 'M': Monday
    • 'T': Tuesday
    • 'W': Wednesday
    • 'H': Thursday
    • 'F': Friday
    • 'S': Saturday
    • 'U': Sunday
  • startTime: show only camps that start during the given time range. Example: startTime=11:00,14:00
  • startDate: show only camps that start on or after the given date. If a range is given, show only camps that start on a date within the given range. Valid examples:
    • startDate=2012-10-05
    • startDate=2012-10-15,2012-12-1
  • endDate: show only camps that end on or before the given date. If a range is given, show only camps that end on a date within the given range. Valid examples:
    • endDate=2012-10-05
    • endDate=2012-10-15,2012-12-1


64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'app/routes/camps.rb', line 64

get %r{^/v#{settings.version}/\d+(/branches/\d+)?(/seasons/\d+)?/camps(\?.*)?$} do
  if params.has_key?('keyword')
    if params["keyword"].present?
      @camps = @camps.search(params[:keyword])
      @camps = @camps.active_with_keyword if params.has_key?('active')
    else
      @camps = @camps.search(params[:keyword])
    end
  end
  @camps = @camps.for_age(params[:age], params.has_key?('months')) if params.has_key?('age')
  @camps = @camps.ssp if params.has_key?('ssp')
  @camps = @camps.current if params.has_key?('current') && !params.has_key?('keyword')
  @camps = @camps.active if params.has_key?('active') && !params.has_key?('keyword')
  @camps = @camps.enabled if params.has_key?('enabled')
  if params.has_key?('day')
    i = 0
    days = %w[U M T W H F S].inject([]) do |arr,day|
      arr << Date::DAYNAMES[i] if params[:day].index(day)
      i += 1
      arr
    end
    @camps = @camps.on_days(days)
  end
  if params.has_key?('startTime')
    time = params[:startTime].split(/,/)
    @camps = @camps.during(time[0], time[1])
  end
  if params.has_key?('startDate')
    dates = params[:startDate].split(/,/)
    @camps =
      if dates.size == 1
        @camps.starting_after(DateTime.parse(dates[0]))
      else
        @camps.starting_between(DateTime.parse(dates[0]),DateTime.parse(dates[1]))
      end
  end
  if params.has_key?('endDate')
    dates = params[:endDate].split(/,/)
    @camps =
      if dates.size == 1
        @camps.ending_before(DateTime.parse(dates[0]))
      else
        @camps.ending_between(DateTime.parse(dates[0]),DateTime.parse(dates[1]))
      end
  end
  extra = {
    :branchCode => lambda {|camp| camp.cc_BranchCode},
    :depositEnabledStaff => lambda {|camp| camp.deposit_enabled_staff},
    :depositEnabledSSP => lambda {|camp| camp.deposit_enabled_ssp},
    :images => lambda { |camp|
      img = camp.image(settings.images, settings.servers); [{ :content => "Image", :href => url(img), :rel => 'image' }] if img
    }
  }

  render_full = params.has_key?('full')
  if render_full
    @camps = @camps.full
    # @camps = @camps.order("CC_ProgramSessions.CC_PS_Order", "CC_AssignedProgramOptions.CC_APO_Order")
    # extra[:customFields] = lambda do |camp|
    #   if [0,2].include? camp.cc_ProgramEnabled
    #     camp_fields = settings.cache.fetch("#{@association.cache_key}_camp_#{camp.id}_fields") { camp.fields }
    #     camp_fields.map {|field| custom_fields(field, 'CC')}
    #   end
    # end
    extra[:links] = lambda {|camp| makelinks(%w[camp_sessions schedules enrollment_priorities]) }
    extra[:depositEnabledStaff] = lambda {|camp| camp.deposit_enabled_staff }
    extra[:depositEnabledSSP] = lambda {|camp| camp.deposit_enabled_ssp }
    extra[:images] = lambda do |camp|
      img = camp.image(settings.images, settings.servers)
      img && [
      { :content => "Image",
        :href => url(img),
        :rel => 'image' }]
    end
    extra[:camp_sessions] = lambda do |camp|
      sessions = []
      camp.sessions.each do |sesh|
        item = api_attributes(sesh)
        item[:links] = makelinks(%w(schedules))
        docs = []
        sesh.camp.document_references.each do |docref|
          doc = docref.document
          if doc
            docs << {
              :name => doc.CDM_DocName,
              :href => url(Document.doc(doc.CDM_DocId, doc.CDM_DocName, settings.servers)),
              :status => docref.ACD_STATUS,
              :branchId => doc.CDM_BranchCode
            }
          end
        end
        item[:documents] = docs
        scheds = []
        sesh.schedules.each do |sched|
          sch = api_attributes(sched)
          #Schedule.preload(sched.id)
          schedule_detail = sched.detail
          schedule_detail_days = schedule_detail.days
          sch[:vacancies] = sched.vacancies
          sch[:name] = schedule_detail.cc_po_Name
          sch[:minDeposit] = sched.min_deposit
          sch[:memberFee] = sched.member_fee
          sch[:nonMemberFee] = sched.non_member_fee
          sch[:programMemberFee] = sched.program_member_fee
          sch[:numberOfDaysToSchedule] = schedule_detail.cc_po_Number_of_Days || -1
          sch[:allowedDays] = (schedule_detail_days.select{|d| d.cc_pod_Status == 1}.map{|d| d.cc_pod_dow} rescue []),
          sch[:type] = sched.type
          sch[:schedule] = schedule_detail_days.map {|day| api_attributes(day)}
          sch[:campId] = camp.id
          scheds << sch
        end
        item[:schedules] = scheds
        sessions << item
      end
      sessions
    end
    extra[:enrollment_priorities] = lambda do |camp|
      priorities = []
      camp.season.enrollment_priorities.each do |priority|
        item = api_attributes(priority)
        priorities << item
      end
      priorities
    end

  end
  render_index(@camps, Camp, extra)
end

- (Object) get("/<api version>/<association id>/categories") - (Object) get("/<api version>/<association id>/branches/<branch id>/categories")

Lists all categories. Optionally filters by branch.

Query Parameters

  • keyword: search for categories by keyword
  • ssp: only show categories set to display in the ssp
  • staff: only show categories set to display in the staff portal
  • nonempty: only show categories that contain nonempty programs (programs with classes)


30
31
32
33
34
35
36
37
38
39
40
41
# File 'app/routes/categories.rb', line 30

get %r{^/v#{settings.version}/\d+(/branches/\d+)?/categories(\?.*)?$} do
  @categories = @categories.search(params[:keyword]) if params.has_key?('keyword')
  @categories = @categories.ssp if params.has_key?('ssp')
  @categories = @categories.staff if params.has_key?('staff')
  @categories = @categories.nonempty if params.has_key?('nonempty')
  render_index(@categories, Category,
    :categoryType => lambda{|category| category.category_type },
    :images => lambda{|category| [
      { :content => "Image",
        :href => url(settings.images + '/' + category.PCM_CategoryImage),
        :rel => 'image' }] unless (!category.PCM_CategoryImage || category.PCM_CategoryImage.empty?)})
end

- (Object) get("/<api version>/<association id>/categories/<category id>") - (Object) get("/<api version>/<association id>/branches/<branch id>/categories/<category id>")

Describes a category.



48
49
50
51
52
53
54
55
56
# File 'app/routes/categories.rb', line 48

get %r{^/v#{settings.version}/\d+(/branches/\d+)?/categories/\d+(\?.*)?$} do
  extra =
    { :links => makelinks(%w[programs classes]) }
  @category.PCM_CategoryImage && !@category.PCM_CategoryImage.empty? && extra[:images] = [
    { :content => "Image",
      :href => url(settings.images + '/' + @category.PCM_CategoryImage),
      :rel => 'image' }]
  render_show(@category, extra)
end

- (Object) get("/<api version>/<association id>/childcare/<childcare id>")

Describes a childcare.



29
30
31
# File 'app/routes/childcares.rb', line 29

get %r{^/v#{settings.version}/\d+/childcares/\d+(\?.*)?$} do
  render_show(@childcare, :links => makelinks(%w[schedules]))
end

- (Object) get("/<api version>/<association id>/childcares")

Lists all childcares.



21
22
23
# File 'app/routes/childcares.rb', line 21

get %r{^/v#{settings.version}/\d+/childcares(\?.*)?$} do
  render_index(@childcares, Childcare)
end

- (JSON) get("/<api version>/<association id>/classes/<class id>") - (JSON) get("/<api version>/<association id>/programs/<program id>/classes/<class id>") - (JSON) get("/<api version>/<association id>/program_sessions/<session id>/classes/<class id>")

Describes a class by it's primary ID

Parameters:

  • memberId

    show the fee for the given member

Returns:

  • (JSON)

    on success



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'app/routes/classes.rb', line 121

get %r{^/v#{settings.version}/\d+(/branches/\d+)?(/categories/\d+)?(/programs/\d+)?(/program_sessions/\d+)?/classes/\d+(\?.*)?$} do
  Course.preload(@course.id)
  extra = { }
  extra[:instructorName] = @course.program_session.PSR_Instructor
  extra[:instructorEmail] = @course.program_session.PSR_InstructorEmail
  extra[:location] = @course.program_session && @course.program_session.location && @course.program_session.location.LM_Location
  extra[:vacancies] = @course.vacancies
  extra[:programId] = @course.program_session.PSR_PM_ProgramID
  extra[:fee] = params[:memberId] && @course.fee(params[:memberId])
  extra[:depositEnabledStaff] = @course.deposit_enabled_staff
  extra[:depositEnabledSSP] = @course.deposit_enabled_ssp
  extra[:memberFee] = @course.member_fee
  extra[:nonMemberFee] = @course.non_member_fee
  extra[:programMemberFee] = @course.program_member_fee
  extra[:salesTax] = api_attributes(@course.sales_tax)
  render_show(@course, extra)
end

- (JSON) get("/<api version>/<association id>/classes") - (JSON) get("/<api version>/<association id>/branches/<branch id>/classes") - (JSON) get("/<api version>/<association id>/categories/<category id>/classes") - (JSON) get("/<api version>/<association id>/programs/<program id>/classes") - (JSON) get("/<api version>/<association id>/program_sessions/<session id>/classes")

Returns on success

Parameters:

  • keyword

    searches for classes using the given query. Will recognize dates, times, program descriptions, category descriptions, or branch names.

  • memberId

    show fees for the given member

  • age

    search for classes available to a given age. Accepts a comma-separated range of ages (such as "4,17") or a single value

  • day

    show only classes that meet on the given days. Accepts a string contaning a combination of the following letters (any order is valid): 'M': Monday 'T': Tuesday 'W': Wednesday 'H': Thursday 'F': Friday 'S': Saturday 'U': Sunday

  • startTime

    show only classes that start during the given time range. Example: startTime=11:00,14:00

  • startDate

    show only classes that start on or after the given date. If a range is given, show only classes that start on a date within the given range. Valid examples: startDate=2012-10-05 or startDate=2012-10-15,2012-12-1

  • endDate

    show only classes that end on or before the given date. If a range is given, show only classes that end on a date within the given range. Valid examples: endDate=2012-10-05 or endDate=2012-10-15,2012-12-1

  • active

    search for active programs

  • current

    search for programs in the current cycle

  • ssp

    show only programs designated as available to the ssp

  • program_number

    show only programs designated with that 5 digit program number. e.g., 02222

Returns:

  • (JSON)

    on success



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'app/routes/classes.rb', line 57

get %r{^/v#{settings.version}/\d+(/branches/\d+)?(/categories/\d+)?(/programs/\d+)?(/program_sessions/\d+)?/classes(\?.*)?$} do
  @courses = @courses.joins(:program_session => :program).where('ProgramMaster.PM_ProgramNo = ?', params[:program_number]) if params.has_key?('program_number')
  if params.has_key?('day')
    i = 0
    days = %w[U M T W H F S].inject([]) do |arr,day|
      arr << Date::ABBR_DAYNAMES[i].upcase if params[:day].index(day)
      i += 1
      arr
    end
    @courses = @courses.on_days(days)
  end
  if params.has_key?('startTime')
    time = params[:startTime].split(/,/)
   @courses =
      if time.size == 1
        @courses.start_time_after(time[0])
      else
        @courses.start_time_between(time[0],time[1])
      end
  end
  if params.has_key?('startDate')
    dates = params[:startDate].split(/,/)
    @courses =
      if dates.size == 1
        @courses.starting_after(DateTime.parse(dates[0]))
      else
        @courses.starting_between(DateTime.parse(dates[0]),DateTime.parse(dates[1]))
      end
  end
  if params.has_key?('endDate')
    dates = params[:endDate].split(/,/)
    @courses =
      if dates.size == 1
        @courses.ending_before(DateTime.parse(dates[0]))
      else
        @courses.ending_between(DateTime.parse(dates[0]),DateTime.parse(dates[1]))
      end
  end
  @courses = @courses.search(params[:keyword]) if params.has_key?('keyword')
  @courses = @courses.for_age(params[:age]) if params.has_key?('age')
  @courses = @courses.current if params.has_key?('current')
  @courses = @courses.active if params.has_key?('active')
  @courses = @courses.ssp if params.has_key?('ssp')
  extra = { :programId => lambda {|course| course.program_session.PSR_PM_ProgramID} }
  extra[:instructorName] = lambda {|course| course.program_session.PSR_Instructor}
  extra[:instructorEmail] = lambda {|course| course.program_session.PSR_InstructorEmail}
  extra[:location] = lambda {|course| course.program_session && course.program_session.location && course.program_session.location.LM_Location }
  extra[:fee] = lambda {|course| course.fee(params[:memberId])} if params.has_key?('memberId')
  extra[:memberFee] = lambda {|course| course.member_fee}
  extra[:nonMemberFee] = lambda {|course| course.non_member_fee}
  extra[:programMemberFee] = lambda {|course| course.program_member_fee}
  extra[:vacancies] = lambda {|course| course.vacancies}
  render_index(@courses, Course, extra)
end

- (JSON, HTML) post("/<api version>/<association id>/corporations")

GET route for viewing corporation by an association.

Corporations for an association.

Returns:

  • (JSON)

    200 (or 404 if blank data is found)

  • (HTML)

    200 (or 404 if blank data is found)



12
13
14
15
# File 'app/routes/corporations.rb', line 12

get %r{^/v#{settings.version}/\d+/corporations?$} do
  @corporations = Corporation.scoped
  render_index(@corporations, Corporation)
end

- (Object) get("/<api version>/<association id>/counter_items/<counter item id>") - (Object) get("/<api version>/<association id>/branches/<branch id>/counter_items/<counter item id>")

Describes a counter item.



33
34
35
# File 'app/routes/counter_items.rb', line 33

get %r{^/v#{settings.version}/\d+(/branches/\d+)?/counter_items/\d+(\?.*)?$} do
  render_show(@counter_item, :salesTax => api_attributes(@counter_item.sales_tax))
end

- (Object) get("/<api version>/<association id>/counter_items") - (Object) get("/<api version>/<association id>/branches/<branch id>/counter_items")

Lists counter items. Optionally filters by branch.



24
25
26
# File 'app/routes/counter_items.rb', line 24

get %r{^/v#{settings.version}/\d+(/branches/\d+)?/counter_items(\?.*)?$} do
  render_index(@counter_items, CounterItem)
end

- (Object) get("/<api version>/<association id>/credits/<credit id>") - (Object) get("/<api version>/<association id>/members/<member id>/credits/<credit id>")

Describes a credit.



31
32
33
# File 'app/routes/credits.rb', line 31

get %r{^/v#{settings.version}/\d+((/families/[^/]+)?/members/[^/]+)?/credits/\d+(\?.*)?$} do
  render_show(@credit)
end

- (Object) get("/<api version>/<association id>/credits") - (Object) get("/<api version>/<association id>/members/<member id>/credits")

Lists online credits. Optionally filters by member.



22
23
24
# File 'app/routes/credits.rb', line 22

get %r{^/v#{settings.version}/\d+((/families/[^/]+)?/members/[^/]+)?/credits(\?.*)?$} do
  render_index(@credits, Credit)
end

- (Object) get("/<api version>/<association id>/donation_prompt")

Describes the donation prompt.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'app/routes/donation_prompt.rb', line 7

get %r{^/v#{settings.version}/\d+/donation_prompt(\?.*)?$} do
  donation_prompt = DonationPrompt.first
  if donation_prompt.present?
    if donation_prompt.enabled?
      images = Array.new
      if donation_prompt.image
        image = donation_prompt.image.FDPI_ImageName
        if not File.exists?("public/images/#{image}")
          f = File.new("public/images/#{image}", "w+b")
          f.write(donation_prompt.image.FDPI_Image)
          f.close
        end
        images = [
                  { :content => "Photo",
                    :href => "/images/#{donation_prompt.image.FDPI_ImageName}",
                    :rel => 'photo' }]
      end
      extra =
        { :images => images,
        :links => [],
        #TODO get rid of both of these, they really don't belong here.
        :appeal => api_attributes(donation_prompt.appeal),
        :staffAppeal => api_attributes(donation_prompt.staff_appeal) }
      #
      extra[:links] <<
        { :content => "Appeal",
        :href => "/v#{settings.version}/#{@association.db.id}/appeals/#{donation_prompt.appeal.id}",
        :rel => 'appeal' } unless donation_prompt.appeal.nil?
      extra[:links] <<
        { :content => "Staff Appeal",
        :href => "/v#{settings.version}/#{@association.db.id}/appeals/#{donation_prompt.staff_appeal.id}",
        :rel => 'staffAppeal' } unless donation_prompt.staff_appeal.nil?
      render_show(donation_prompt, extra, true)
    else
      halt_record_not_found
    end
  else
    halt_record_not_found
  end
end

- (JSON, HTML) get("/<api version>/<association id>/retrieve")

GET route for retreiving family details and sending a password reset email, or a 400.

Send Email to an association.

Parameters:

  • email

    email address (required)

  • phone

    phone number is optional, but passed in addition to the email too.

Returns:

  • (JSON)

    200 (or 40 if blank data is found)

  • (HTML)

    200 (or 404 if blank data is found)



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'app/routes/emails.rb', line 52

get %r{^/v#{settings.version}/\d+/retrieve?$} do
#  post %r{^/v#{settings.version}/\d+/families/email?$} do
  data = params
  # case request.content_type
  # when /json/ then JSON.parse(request.body.read)
  # else params
  # end
  #return if no email or phone
  if data["email"].present?
    families = Family.search_by_email(data["email"])
    if families.blank?
      families = Member.search_by_member_email(data['email'])
    end
    unless families.blank?
      if families.count == 1
        send_mail(families.first, data['email'])
      elsif families.count > 1
        if data['phone'].present?
          phone_no = setup_phone_search(data['phone'])
          member_phone_param = phoneify(data['phone'], true)
          family = []
          families.each do |fam|
            if fam.is_a?(Family)
              the_search = fam.search_by_phone(phone_no)
              family << the_search.first if the_search.present?
            else
              family << fam if fam.match_phone(member_phone_param)
            end
          end
          if family.count == 1
            send_mail(family.first, data['email'])
          else
            family = Family.(families)
            if family.count == 1
              send_mail(family.first, data['email'])
            else
              halt_with_error(413, "Multiple Families still applicable. Contact the organization to clarify")
            end
          end
        else
          halt_with_error(416, "Too many records found with that email address, send again with email and phone number params")
        end
      end
    else
      halt_record_not_found
    end
  elsif data['phone'].present? && data["email"].present?
    phone_no = setup_phone_search(data['phone'])
    family = Family.search_by_phone(phone_no)
    if families.count > 0
      halt_with_error(413, "Multiple Families still applicalbe. Contact the organization to clarify")
    else
      halt 200, "Proceed to Checkout"
    end
  else
    halt_with_error(400, "Need the email and or the phone")
  end
end

- (JSON, HTML) post("/<api version>/<association id>/emails")

POST route for sending an email to an association.

Send Email to an association.

Parameters:

  • family_id

    used as the email sender

  • subject

    email subject

  • body

    email body

  • from

    email optional if no family id present.

  • name

    email optional if no family id present.

Returns:

  • (JSON)

    200 (or 404 if blank data is found)

  • (HTML)

    200 (or 404 if blank data is found)



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'app/routes/emails.rb', line 15

post %r{^/v#{settings.version}/\d+/email?$} do
  data =
    case request.content_type
    when /json/ then JSON.parse(request.body.read)
    else params
    end
  #find_family_member
  RestClient.log.debug(data.inspect)
  add_headers
  the_email =
    if data["family_id"].present?
      family = Family.find(data["family_id"])
      family.FC_Email
    else
      data["from"]
    end
  the_name = data["family_id"].present? ? family.primary_member.full_name : data["name"]
  RestClient.log.debug(the_email.present? && data["subject"].present? && data["body"].present?)
  if the_email.present? && data["subject"].present? && data["body"].present?
    the_mailer = Mailer.new(@association.y_email, the_email, the_name)
    the_mail = the_mailer.generic_inquiry(data["subject"], data["body"])
    RestClient.log.debug("---sending #{the_mail.inspect}")
    the_mailer.delivering(the_mail)
    halt 200, {'Content-Type' => 'application/json'}, {"body" => "You have sent an email"}.to_json
  else
    halt_record_not_found
  end
end

- (Object) get(/<api version>/<associationid>/members/<memberid>/emergency_contacts/<emergency_contactid>)

Returns the emergency_contact record based on it's id and on the member id



37
38
39
40
# File 'app/routes/emergency_contacts.rb', line 37

get %r{^/v#{settings.version}/\d+/members/[^/]+?/emergency_contacts/(\d+)?$} do |the_id|
  @emergency_contact = EmergencyContact.where(:cc_EMER_id => the_id).first
  render_show(@emergency_contact)
end

- (Object) get(/<api version>/<associationid>/members/<memberid>/emergency_contacts)

Find out information about a Camp Participant's EmergencyContact

Returns all EmergencyContacts for a member id



8
9
10
11
12
# File 'app/routes/emergency_contacts.rb', line 8

get %r{^/v#{settings.version}/\d+/members/[^/]+?/emergency_contacts(\?.*)?$} do
  @emergency_contacts = EmergencyContact.where(:cc_EMER_cc_par => @member.participant.id) #EmergencyContact.execute_procedure(:cc_GetAuthorizedEmergencyContact, @member.participant.id)

  render_index(@emergency_contacts, EmergencyContact)
end

- (Object) get("/<api version>/<association id>/programs/<program id>/enrollment_priorities") - (Object) get("/<api version>/<association id>/camps/<camp id>/enrollment_priorities")

Lists program or camp enrollment priorities. Optionally shows eligibility for a member.

Query Parameters

  • memberId: Member for which the eligibility needs to be determined


29
30
31
32
33
34
35
36
37
38
# File 'app/routes/enrollment_priorities.rb', line 29

get %r{^/v#{settings.version}/\d+((/branches/\d+)?(/categories/\d+)?/programs/\d+|(/branches/\d+)?(/seasons/\d+)?/camps/\d+)?/enrollment_priorities(\?.*)?$} do
  if params[:memberId]
    member = Member.find(params[:memberId])
    !member && halt(400, "Invalid member id.")
    render_index(@priorities, EnrollmentPriority,
      {:memberEligible => lambda {|ep| ep.is_eligible?(member)}})
  else
    render_index(@priorities, EnrollmentPriority)
  end
end

- (Object) get("/<api version>/<association id>/programs/<program id>/enrollment_priorities/<enrollment priority id>") - (Object) get("/<api version>/<association id>/camps/<camp id>/enrollment_priorities/<enrollment priority id>")

Describes an enrollment priority.



45
46
47
48
49
50
51
# File 'app/routes/enrollment_priorities.rb', line 45

get %r{^/v#{settings.version}/\d+((/branches/\d+)?(/categories/\d+)?/programs/\d+|(/branches/\d+)?(/seasons/\d+)?/camps/\d+)?/enrollment_priorities/\d+(\?.*)?$} do
  if params[:memberId]
    member = Member.find(params[:memberId])
    !member && halt(400, "Invalid member id.")
  end
  member ? render_show(@priority, :memberEligible => @priority.is_eligible?(member)) : render_show(@priority)
end

- (Object) get("/<api version>/<association id>/families")

Lists all families



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'app/routes/families.rb', line 21

get %r{^/v#{settings.version}/\d+/(family_connections|families)(\?.*)?$} do
  extras = Hash.new
  @sanitized_includes = Family.sanitized_includes(@parsed_request.includes)

  if @sanitized_includes
    @sanitized_includes.each do |k,v|
      if Family.reflect_on_all_associations.map(&:name).include? k.to_sym
        @families = @families.includes(k.to_sym)
        extras[k.to_sym] = lambda { |f| f.send(k.to_sym).map { |m| inject_model_attributes m } }
      else
        extras[MAPPINGS[:families] && MAPPINGS[:families][k]] = lambda { |f| f.send(k.to_sym) }
      end
    end
  end

  render_index(@families, Family, extras)
end

- (Object) get("/<api version>/<association id>/families/<family id>")

Describes a family.



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'app/routes/families.rb', line 69

get %r{^/v#{settings.version}/\d+/(family_connections|families)/(?!authenticate)[^/]+(\?.*)?$} do
  headers "X-Family-ID" => @family.id
  @extras = {
    :links => makelinks(%w(members payment_instruments)),
    :nonEpayMemberCount => @family.non_epay_members,
    :active_credits => @family.active_credits
  }
  @sanitized_includes = Family.sanitized_includes(@parsed_request.includes)

  if @sanitized_includes
    @sanitized_includes.each do |k,v|
      if Family.reflect_on_all_associations.map(&:name).include? k.to_sym
        @extras[k.to_sym] = @family.send(k.to_sym).map { |m| inject_model_attributes m }
      else
        @extras[k.to_sym] = @family.send(k.to_sym)
      end
    end
  end
  render_show @family, @extras
end

- (JSON, HTML) get("/<api version>/<association id>/gift_cards/<gift card id>") - (JSON, HTML) get("/<api version>/<association id>/members/<member id>/gift_cards/<gift card id>")

Describes a gift card.

Returns:

  • (JSON)

    if the gift card id is successfully found

  • (HTML)

    if sent from a browser, for the successfully found

Extra Information Returned:

  • links

    to Gift Card Transaction

  • balance

    Gift Card Balance

  • uses

    returns the uses of Gift Card



44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'app/routes/gift_cards.rb', line 44

get %r{^/v#{settings.version}/\d+(/members/[^/]+)?/gift_cards/\d+(\?.*)?$} do
  links = Array.new
  @gift_card.transaction && links <<
    { :content => "Purchase Transaction",
      :href => "/v#{settings.version}/#{@association.db.id}/transactions/#{@gift_card.transaction.id}",
      :rel => "purchaseTransaction" }
  uses = Array.new
  @gift_card.uses &&
    uses = @gift_card.uses.map {|use| api_attributes(use)}
  render_show(@gift_card,
    :balance => @gift_card.balance,
    :uses => uses,
    :links => links | makelinks(%w[receipts transactions]))
end

- (JSON, HTML) get(/<api version>/<associationid>/gift_cards) - (JSON, HTML) get(/<api version>/<associationid>/members/<memberid>/gift_cards)

Lists gift cards. Optionally filters by member.

Query Parameters

Parameters:

  • number

    search for gift card by number

Returns:

  • (JSON)

    of all gift_cards that match or if number param sent and is successful, then that page will show

  • (HTML)

    shown if sent from a browser



29
30
31
32
# File 'app/routes/gift_cards.rb', line 29

get %r{^/v#{settings.version}/\d+(/members/[^/]+)?/gift_cards(\?.*)?$} do
  @gift_cards = @gift_cards.where(:GCM_CardNo => params[:number]) if params.has_key?('number')
  render_index(@gift_cards, GiftCard)
end

- (Object) get(/<api version>/<associationid>/members/<memberid>/immunizations/<immunizationid>)

Returns the immunization record based on it's id and on the member id



32
33
34
35
# File 'app/routes/immunizations.rb', line 32

get %r{^/v#{settings.version}/\d+/members/[^/]+?/immunizations/(\d+)?$} do |the_id|
  @immunization = Immunization.where(:CC_IMS_ID => the_id).first
  render_show(@immunization)
end

- (Object) get(/<api version>/<associationid>/members/<memberid>/immunizations)

Find out information about a Camp Participant's Immunization

Returns all Immunizations for a member id



8
9
10
11
12
# File 'app/routes/immunizations.rb', line 8

get %r{^/v#{settings.version}/\d+/members/[^/]+?/immunizations(\?.*)?$} do
  @immunizations = Immunization.where(:CC_IMS_CC_PAR => @member.participant.id) #Immunization.execute_procedure(:cc_GetAuthorizedImmunization, @member.participant.id)

  render_index(@immunizations, Immunization)
end

- (Object) get("/<api version>/<association id>/invoices/<invoice id>") - (Object) get("/<api version>/<association id>/members/<member id>/invoices/<invoice id>")

Describes an invoice.



31
32
33
# File 'app/routes/invoices.rb', line 31

get %r{^/v#{settings.version}/\d+(/members/[^/]+)?/invoices/\d+(\?.*)?$} do
  render_show(@invoice, :details => @invoice.details.map{|detail| api_attributes(detail)})
end

- (Object) get("/<api version>/<association id>/invoices") - (Object) get("/<api version>/<association id>/members/<member id>/invoices")

Lists invoices. Optionally filters by member.



22
23
24
# File 'app/routes/invoices.rb', line 22

get %r{^/v#{settings.version}/\d+(/members/[^/]+)?/invoices(\?.*)?$} do
  render_index(@invoices, Invoice)
end

- (Object) get(/<api version>/<associationid>/members/<memberid>/medical_contacts/<medical_contactid>)

Returns the medical_contact record based on it's id and on the member id



35
36
37
38
# File 'app/routes/medical_contacts.rb', line 35

get %r{^/v#{settings.version}/\d+/members/[^/]+?/medical_contacts/(\d+)?$} do |the_id|
  @medical_contact = MedicalContact.where(:cc_MED_id => the_id).first
  render_show(@medical_contact)
end

- (Object) get(/<api version>/<associationid>/members/<memberid>/medical_contacts)

Find out information about a Camp Participant's MedicalContact

Returns all MedicalContacts for a member id



8
9
10
11
# File 'app/routes/medical_contacts.rb', line 8

get %r{^/v#{settings.version}/\d+/members/[^/]+?/medical_contacts(\?.*)?$} do
  @medical_contacts = MedicalContact.where(:cc_MED_cc_par => @member.participant.id) #MedicalContact.execute_procedure(:cc_GetAuthorizedMedicalContact, @member.participant.id)
  render_index(@medical_contacts, MedicalContact)
end

- (JSON, HTML) get(/<api version>/<associationid>/members/<memberid>) - (JSON, HTML) get(/<api version>/<associationid>/families/<familyid>/members/<memberid>)

Describes a member.

Pass the member_id to this route. Upon finding a valid member in the database, the following information is returned (if applicable)

Returns:

  • (JSON)

    of all applicable member information

  • (HTML)

    of all applicable member information if using a web browser

Membership Info Returned:

  • membership_type

    Information about their membership type

  • membership_draft_type

    Information about their membership draft type

  • membership_statuses

    (if applicable) Information about their membership

  • membership_links

    links to their membership

  • membership_fees

    Information about their membership_fees in $

Http Headers Returned:

  • X-Member-ID

    contains the member_id

Extra Information Returned:

  • address

    member's address

  • isSponsor

    true or false

  • hasCampEpay

    true or false

  • isParticipant

    true or false

  • links

    links to a memeber's [receipts gift_cards pledges invoices scans subsidies balances credits]

  • demographics

    member demographic

  • customFieldValues

    member custom_field_values iterated

  • campCustomFieldValues

    member participant custom_field_values iterated (if applicable)

  • enrolledPrograms

    enrolled_programs for the member

  • enrolledCamps

    enrolled_camps for member

  • enrolledChildcares

    enrolled_childcares

  • images

    [{ :content => "Photo", :href => link to image, :rel => "photo" }]}

Membership:

  • If a member also has a membership, information will be returned regarding that membership. This includes: :membership => Information about their membership Inside the :membership array will be (see Membership Info Returned)



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'app/routes/members.rb', line 187

get %r{^/v#{settings.version}/\d+(/(families|family_connections)/[^/]+)?/members/[^/]+(\?.*)?$} do
  # notifi-ize hash (takes keys.each "_" + key)
  log_hash = {
    :short_message => "debug member",
    :full_message => "I am the full message",
    :_local_time => Time.now,
    :_zone_time => Time.zone.now,
    :_association_id => @association.id,
  }
  log_hash[:_family_id] = @family.id if @family
  log_hash[:_member_id] = @member.id if @member
  settings.notifier.notify!(log_hash)
  headers "X-Member-ID" => @member.id
  extra =
    { :address => api_attributes(settings.cache.fetch("#{@association.cache_key}_member_#{@member.id}_address") { @member.address }),
    :isSponsor => !@member.sponsor.nil?,
    :vac_card_number => @member.find_vac_card_number,
      :hasCampEpay => @member.sponsor.try(:cc_sponsor_Is_Camp_Epay) == 1,
      :isParticipant => !@member.participant.nil?,
      :links => makelinks(%w[receipts gift_cards pledges invoices scans subsidies balances credits]),
      :demographics => api_attributes(settings.cache.fetch("#{@association.cache_key}_member_#{@member.id}_demographic") { @member.demographic }),
      :customFieldValues => settings.cache.fetch("#{@association.cache_key}_member_#{@member.id}_custom_field_values") { @member.custom_field_values }.map {|value| api_attributes(value)},
      :campCustomFieldValues => @member.participant && @member.participant.custom_field_values.map {|value| api_attributes(value)},
      :enrolledPrograms => settings.cache.fetch("#{@association.cache_key}_member_#{@member.id}_enrolled_programs") { @member.enrolled_programs },
      :enrolledCamps => settings.cache.fetch("#{@association.cache_key}_member_#{@member.id}_enrolled_camps") { @member.enrolled_camps },
      :enrolledChildcares => settings.cache.fetch("#{@association.cache_key}_member_#{@member.id}_enrolled_childcares") { @member.enrolled_childcares},
      :images => [{
        :content => "Photo",
        :href => member_image_link(@association, @member, false),
                    :rel => "photo" }]}
  @membership = @member.membership
  if @membership.present?
    extra[:membership] = api_attributes @membership
    extra[:membership][:type] = @membership.type.membershipType
    extra[:membership][:draftType], extra[:membership][:draftAccount] =
      case @membership.payment_instrument.EP_ActiveDraftType
        when 1 then ["Credit Card", @membership.payment_instrument.EP_ReportCCNo]
        when 2 then ["Bank", "XXXX" + @membership.payment_instrument.EP_Account[-4..-1]]
      end if @membership.payment_instrument
    if @membership.statuses
      extra[:membership][:membershipStatuses] = @membership.statuses.map do |status|
        api_attributes(status).merge(api_attributes(status.type))
      end
    end
    if @membership.membership && @membership.ySysMemId != 0
      extra[:links] <<
        { :content => "Membership",
          :href => "/v#{settings.version}/#{@association.db.id}/memberships/#{@membership.membership.id}",
          :rel => "membership" }
    end
    extra[:membership][:membership_fees] = @membership.get_membership_fees(@membership.billableMemberId) unless extra[:membership][:type].blank?
    extra[:membership][:membership_fees].each {|d| d["fee"] = d["fee"].to_f} unless extra[:membership][:membership_fees].blank?
  end
  render_show(@member, extra)
end

- (Object) get("/<api version>/<association id>/members/<member id>/balances/<balance id>")

Describes an outstanding balances for a member.



258
259
260
# File 'app/routes/members.rb', line 258

get %r{^/v#{settings.version}/\d+(/(families|family_connections)/[^/]+)?/members/[^/]+/balances/[^/]+(\?.*)?$} do
  render_show(@balance)
end

- (Object) get("/<api version>/<association id>/members/<member id>/balances")

Lists outstanding balances for a member.



247
248
249
250
251
252
# File 'app/routes/members.rb', line 247

get %r{^/v#{settings.version}/\d+(/(families|family_connections)/[^/]+)?/members/[^/]+/balances(\?.*)?$} do
  # TODO: undefined method `model_name' for Balance:Class
  # because Balance isn't an AR Model
  # TODO: figure out why limit/offset aren't working
  render_index(@member.balances, Balance)
end

- (JSON, HTML) get("/<api version>/<association id>/members") - (JSON, HTML) get("/<api version>/<association id>/families/<family id>/members")

GET route for information about an Association or Family's members. Accepts paramaters for filtering too.

Overloads:

  • - (JSON, HTML) get("/<api version>/<association id>/members")

    Lists all members for an association.

  • - (JSON, HTML) get("/<api version>/<association id>/families/<family id>/members")

    Returns only members for a given family connection.

Parameters:

  • phone

    search for members by phone number

  • email

    search for members by email address

  • address1

    search for members by address1

  • address2

    search for members by address2

  • city

    search for members by city

  • state

    search for members by state

  • zip

    search for members by zip code

  • reset

    used to resend password. When resetting a password, you must pass either email or phone param alond with reset. /v.2/10/members?phone=4165552222&reset=

Returns:

  • (JSON)

    of all information regarding the members

  • (HTML)

    if you are on the browser looking at this route



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'app/routes/members.rb', line 45

get %r{^/v#{settings.version}/\d+(/(families|family_connections)/[^/]+)?/members(\?.*)?$} do

  if params.has_key?('phone')
    match = setup_phone_search(params[:phone])
    @members = @members.by_phone(match)
  end
  if params.has_key?('reset')
    if params.has_key?('email') || params.has_key?('phone')
      @members = @members.find_by_the_family_email(params[:email]) if params.has_key?('email')
      if @members.group(:familyId).count.one?
        @member = @members.first # if the same family
        member_email = @member.family.FC_Email
        base_url = @association.Y_Base_Url
        the_token = @member.get_the_password_token
        if the_token.present?
          reset_url = base_url + "/Account/Retrieve?token=" + the_token
          the_mailer = Mailer.new(member_email, @association.y_email, @association.y_name)
          the_mail = the_mailer.reset_password(@member.family.FC_LoginID, reset_url)
          the_mailer.delivering(the_mail)
        end
      else
        halt_with_error(400, "Multiple Matching Accounts found")
      end
    end
  else
    if params.has_key?('zip')
      match = zipify(params[:zip])
      match = "%" + match[0,5] + "%" + match[6,4]
      @members = @members.joins(:address).where("NVC_Address.zip LIKE ?", match)
    end
    @members = @members.find_email(params[:email]) if params.has_key?('email')
    @members = @members.find_address1(params[:address1]) if params.has_key?('address1')
    @members = @members.find_address2(params[:address2]) if params.has_key?('address2')
    @members = @members.find_city(params[:city]) if params.has_key?('city')
    @members = @members.find_state(params[:state]) if params.has_key?('state')
    #send email for password reset

  end
  render_index(@members, Member, :email => lambda {|member| member.email})
end

- (Object) get("/<api version>/<association id>/memberships/<membership id>") - (Object) get("/<api version>/<association id>/branches/<branch id>/memberships/<membership id>") - (Object) get("/<api version>/<association id>/membership_categories/<membership category id>/memberships/<membership id>")

Describes a membership.

GET route for membership information about a single membership ID from either an Association, a Branch or Membership Category. This route returns: :categoryId => the category id of the Membership :fees => All fees that include sales_tax

See Also:



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'app/routes/memberships.rb', line 66

get %r{^/v#{settings.version}/\d+(/branches/\d+)?(/membership_categories/\d+)?/memberships/\d+(\?.*)?$} do
  render_show(@membership,
    :categoryId => @membership.category.id,
              :fees => @membership.fees.includes(:sales_tax).map do |fee|
                the_fee = api_attributes(fee)
                the_fee.merge!(:salesTax => api_attributes(fee.sales_tax))
                if fee.ProrateByDefault == 1
                  if @membership.PAYMETH == "Monthly"|| @membership.PAYMETH == "Monthly E-Pay"
                    the_offset = @association.customizations.TimeZone
                    next_date = @association.customizations.get_next_billing_date
                    the_fee.merge!(:proratedFee => fee.get_prorated_fee(the_offset, next_date))
                  end
                end
                the_fee
              end)
end

- (Object) get("/<api version>/<association id>/membership_categories") - (Object) get("/<api version>/<association id>/branches/<branch id>/membership_categories")

Lists all membership categories. Optionally filters by branch.

Query Parameters

  • keyword: search for membership categories by keyword
  • ssp: show only membership categories marked for display on the ssp
  • active: show only active membership categories


31
32
33
34
35
36
37
# File 'app/routes/membership_categories.rb', line 31

get %r{^/v#{settings.version}/\d+(/branches/\d+)?/membership_categories(\?.*)?$} do
  @categories = @categories.search(params[:keyword]) if params.has_key?("keyword")
  filters = []
  %w[ssp active].each {|str| filters << str.to_sym if params.has_key?(str)}
  filters.each {|filter| @categories = @categories.send(filter)}
  render_index @categories, MembershipCategory
end

- (Object) get("/<api version>/<association id>/membership_categories/<membership category id>") - (Object) get("/<api version>/<association id>/branches/<branch id>/membership_categories/<membership category id>")

Describes a membership category.



44
45
46
# File 'app/routes/membership_categories.rb', line 44

get %r{^/v#{settings.version}/\d+(/branches/\d+)?/membership_categories/\d+(\?.*)?$} do
  render_show @category, :links => makelinks(%w[memberships])
end

- (JSON, HTML) get("/<api version>/<association id>/memberships") - (JSON, HTML) get("/<api version>/<association id>/branches/<branch id>/memberships") - (JSON, HTML) get("/<api version>/<association id>/membership_categories/<membership category id>/memberships")

GET route for all membership information about an Association, a Branch or Membership Category. Accepts paramaters for filtering too.

Overloads:

  • - (JSON, HTML) get("/<api version>/<association id>/memberships")

    Lists all members for an association

  • - (JSON, HTML) get("/<api version>/<association id>/branches/<branch id>/memberships")

    Lists all members for a branch

  • - (JSON, HTML) get("/<api version>/<association id>/membership_categories/<membership category id>/memberships")

    Lists all members for a Membership Category

Parameters:

  • keyword

    search for memberships by keyword

  • active

    show only active memberships

  • ssp

    show only memberships marked for display on the ssp

  • age

    search for programs available to a given age. Accepts a comma-separated range of ages (such as "4,17") or a single value

Returns:

  • (JSON)

    for information on all memberships

  • (HTML)

    for information on all memberships if displayed in a browser



45
46
47
48
49
50
51
52
# File 'app/routes/memberships.rb', line 45

get %r{^/v#{settings.version}/\d+(/branches/\d+)?(/membership_categories/\d+)?/memberships(\?.*)?$} do
  @memberships = @memberships.search(params[:keyword]) if params.has_key?('keyword')
  @memberships = @memberships.active if params.has_key?('active')
  @memberships = @memberships.ssp if params.has_key?('ssp')
  @memberships = @memberships.for_age(params[:age]) if params.has_key?('age')
  render_index(@memberships, Membership,
    { :categoryId => lambda {|membership| membership.category.id} })
end

- (Object) get("/<api version>/<assocation id>/families/<family id>/payment_instruments/<payment instrument id>)

Returns details for a payment instrument



31
32
33
# File 'app/routes/payment_instruments.rb', line 31

get %r{^/v#{settings.version}/\d+/families/[^/]+/payment_instruments/\d+$} do
  render_show(@payment_instrument)
end

- (Object) get("/<api version>/<assocation id>/families/<family id>/payment_instruments)

List payment instruments, such as credit cards associated with a family or member. The list of payment instruments is called an e-Wallet

Note: Currently, only family e-Wallets are supported.



23
24
25
# File 'app/routes/payment_instruments.rb', line 23

get %r{^/v#{settings.version}/\d+/families/[^/]+/payment_instruments(\?.*)?$} do
  render_index(@payment_instruments, PaymentInstrument)
end

- (JSON, HTML) get("/<api version>/<association id>/families/<family id>/peding_receipts")

Used to clear receipts or verify POST is going to be submitted to PayPal.

Clears pending receipts for the family.

Returns:

  • (JSON)

    204 if there are receipts, 200 if none.

  • (HTML)

    204 if there are receipts, 200 if none.



24
25
26
27
28
29
30
31
32
33
# File 'app/routes/pending_receipts.rb', line 24

get %r{^/v#{settings.version}/\d+/families/[^/]+?/pending_receipts(\?.*)?$} do
  paypal_config = @association.pay_pal_configuration
  the_receipts = @the_family.flush_temporary_transactions(paypal_config)
  if the_receipts.present?
    handle_unfinalized_receipts(the_receipts, paypal_config)
    halt 204
  else
    halt 200
  end
end

- (Object) get(/<api version>/<associationid>/members/<memberid>/pickup/<pickupid>)

Returns the pickup record based on it's id and on the member id



38
39
40
41
# File 'app/routes/pickups.rb', line 38

get %r{^/v#{settings.version}/\d+/members/[^/]+?/pickups/(\d+)?$} do |the_id|
  @pickup = Pickup.where(:cc_apu_id => the_id).first
  render_show(@pickup)
end

- (Object) get(/<api version>/<associationid>/members/<memberid>/pickups)

Find out information about a Camp Participant's Pickup

Returns all Pickups for a member id



8
9
10
11
12
# File 'app/routes/pickups.rb', line 8

get %r{^/v#{settings.version}/\d+/members/[^/]+?/pickups(\?.*)?$} do
  @pickups = Pickup.where(:cc_apu_cc_par => @member.participant.id) #Pickup.execute_procedure(:cc_GetAuthorizedPickUp, @member.participant.id)

  render_index(@pickups, Pickup)
end

- (Object) get("/<api version>/<association id>/pledges/<pledge id>") - (Object) get("/<api version>/<association id>/appeals/<appeal id>/pledges/<pledge id>") - (Object) get("/<api version>/<association id>/members/<member id>/pledges/<pledge id>")

Describes a pledge.



38
39
40
# File 'app/routes/pledges.rb', line 38

get %r{^/v#{settings.version}/\d+((/campaigns/\d+)?/appeals/\d+|(/families/[^/]+)?/members/[^/]+)?/pledges/\d+(\?.*)?$} do
  render_show(@pledge, :category => @pledge.category.FRPC_Name)
end

- (Object) get("/<api version>/<association id>/pledges") - (Object) get("/<api version>/<association id>/appeals/<appeal id>/pledges") - (Object) get("/<api version>/<association id>/members/<member id>/pledges")

Lists pledges. Optionally filters by member or appeal.



28
29
30
# File 'app/routes/pledges.rb', line 28

get %r{^/v#{settings.version}/\d+((/campaigns/\d+)?/appeals/\d+|(/families/[^/]+)?/members/[^/]+)?/pledges(\?.*)?$} do
  render_index(@pledges, Pledge)
end

- (Object) get("/<api version>/<association id>/programs/<program id>") - (Object) get("/<api version>/<association id>/branches/<branch id>/programs/<program id>") - (Object) get("/<api version>/<association id>/categories/<category id>/programs/<program id>")

Describes a program.



181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'app/routes/programs.rb', line 181

get %r{^/v#{settings.version}/\d+(/branches/\d+)?(/categories/\d+)?/programs/\d+(\?.*)?$} do
  Program.preload(@program.id)
  img = @program.image(settings.images, settings.servers)
  extra =
    { :cycle => api_attributes(@program.cycle),
      :links => makelinks(%w[program_sessions classes enrollment_priorities]),
      :images => img && [
        { :content => "Image",
          :href => url(img),
          :rel => 'image' }]}
  extra[:customFields] = @program.fields.map {|field| custom_fields(field, 'NVC')} if [0,2].include? @program.PM_CustomFieldEnabled
  extra[:categoryId] = @program.program_joins.first.CCR_PCM_ID unless @program.program_joins.empty?
  render_show(@program, extra)
end

- (Object) get("/<api version>/<association id>/program_sessions/<session id>") - (Object) get("/<api version>/<association id>/programs/<program id>/program_sessions/<session id>")

Describes a program session.



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'app/routes/program_sessions.rb', line 34

get %r{^/v#{settings.version}/\d+((/branches/\d+)?(/categories/\d+)?/programs/\d+)?/program_sessions/\d+(\?.*)?$} do
  extra =
    { :location => api_attributes(@session.location),
      :links => makelinks(%w(classes)) }
  extra[:documents] = Array.new
  @session.document_references.each do |document|
    doc = Document.select([:CDM_DocName, :CDM_DocId, :CDM_BranchCode]).find(document.ACD_CDM_DocId)
    extra[:documents] <<
      { :name => doc.CDM_DocName,
        :href => url(Document.doc(doc.CDM_DocId, doc.CDM_DocName, settings.servers)),
        :status => document.ACD_STATUS,
        :branchId => doc.CDM_BranchCode }
  end
  render_show(@session, extra)
end

- (Object) get("/<api version>/<association id>/program_sessions") - (Object) get("/<api version>/<association id>/programs/<program id>/program_sessions")

Lists all program sessions. Optionally filters by program.



25
26
27
# File 'app/routes/program_sessions.rb', line 25

get %r{^/v#{settings.version}/\d+((/branches/\d+)?(/categories/\d+)?/programs/\d+)?/program_sessions(\?.*)?$} do
  render_index(@sessions, ProgramSession)
end

- (JSON) get("/<api version>/<association id>/programs") - (JSON) get("/<api version>/<association id>/branches/<branch id>/programs") - (JSON) get("/<api version>/<association id>/categories/<category id>/programs")

Lists all programs. Optionally filters by branch or category.

Parameters:

  • keyword

    search for programs by keyword

  • day

    show only classes that meet on the given days. Accepts a string contaning a combination of the following letters (any order is valid): 'M': Monday 'T': Tuesday 'W': Wednesday 'H': Thursday 'F': Friday 'S': Saturday 'U': Sunday

  • startTime

    show only classes that start during the given time range. Example: startTime=11:00,14:00

  • startDate

    show only classes that start on or after the given date. If a range is given, show only classes that start on a date within the given range. Valid examples: startDate=2012-10-05 startDate=2012-10-15,2012-12-1

  • endDate

    show only classes that end on or before the given date. If a range is given, show only classes that end on a date within the given range. Valid examples: endDate=2012-10-05 endDate=2012-10-15,2012-12-1

  • age

    search for programs available to a given age. Accepts a comma-separated range of ages (such as "4,17") or a single value

  • current

    search for programs in the current cycle

  • active

    search for active programs

  • nonempty

    show only programs with classes

  • ssp

    show only programs designated as available to the ssp

  • program_number

    show only programs designated with that 5 digit program number. e.g., 02222

Returns:

  • (JSON)

    on success



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'app/routes/programs.rb', line 57

get %r{^/v#{settings.version}/\d+(/branches/\d+)?(/categories/\d+)?/programs(\?.*)?$} do
  if params.has_key?('keyword')
    keyword = params[:keyword].valid_encoding? ? params[:keyword] : "nothing"
    @programs = @programs.search(keyword)
  end
  @programs = @programs.by_branches(params[:branches].split(/,/)) if params.has_key?('branches')
  @programs = @programs.by_categories(params[:categories].split(/,/)) if params.has_key?('categories')
  @programs = @programs.for_age(params[:age]) if params.has_key?('age')
  @programs = @programs.where(PM_ProgramNo: params[:program_number]) if params.has_key?('program_number')
  @programs = @programs.current if params.has_key?('current')
  @programs = @programs.active if params.has_key?('active')
  @programs = @programs.nonempty if params.has_key?('nonempty')
  @programs = @programs.ssp if params.has_key?('ssp')
  if params.has_key?('day')
    i = 0
    the_day = params[:day].upcase
    days = %w[U M T W H F S].inject([]) do |arr,day|
      arr << Date::ABBR_DAYNAMES[i].upcase if the_day.index(day)
      i += 1
      arr
    end
    @programs = @programs.on_days(days)
  end
  if params.has_key?('startTime')
    time = params[:startTime].split(/,/)
    @programs = @programs.during(time[0], time[1])
  end
  if params.has_key?('startDate')
    dates = params[:startDate].split(/,/)
    @programs =
      if dates.size == 1
        @programs.starting_after(DateTime.parse(dates[0]))
      else
        @programs.starting_between(DateTime.parse(dates[0]),DateTime.parse(dates[1]))
      end
  end
  if params.has_key?('endDate')
    dates = params[:endDate].split(/,/)
    @programs =
      if dates.size == 1
        @programs.ending_before(DateTime.parse(dates[0]))
      else
        @programs.ending_between(DateTime.parse(dates[0]),DateTime.parse(dates[1]))
      end
  end
  extra =
  {
    :categoryId => lambda {|program| program.program_joins.first.CCR_PCM_ID unless program.program_joins.empty?},
    :images => lambda do |program|
      img = program.image(settings.images, settings.servers)
      if img
        [{ :content => "Image",
           :href => url(img),
           :rel => 'image' }]
      end
    end
  }

  render_full = params.has_key?('full')
  if render_full
    @programs = @programs.full
    extra[:customFields] = lambda {|program| program.fields.map {|field| custom_fields(field, 'NVC')} if [0,2].include? program.PM_CustomFieldEnabled }
    extra[:links] = lambda {|program| makelinks(%w[program_sessions classes enrollment_priorities]) }
    extra[:cycle] = lambda {|program| api_attributes(program.cycle) }
    extra[:classes] = lambda do |program|
      classes = []
      courses = params.has_key?("active") ? program.courses.current.active : program.courses
      courses.each do |course|
        Course.preload(course.id)
        item = api_attributes(course)
        item[:vacancies] = course.display_vacancy
        item[:programId] = program.PM_PROGRAMID
        item[:depositEnabledStaff] = course.deposit_enabled_staff
        item[:depositEnabledSSP] = course.deposit_enabled_ssp
        item[:memberFee] = course.member_fee
        item[:nonMemberFee] = course.non_member_fee
        item[:programMemberFee] = course.program_member_fee
        item[:salesTax] = api_attributes(course.sales_tax)
        classes << item
      end
      classes
    end
    extra[:enrollment_priorities] = lambda do |program|
      priorities = []
      program.cycle.enrollment_priorities.each do |priority|
        item = api_attributes(priority)
        priorities << item
      end
      priorities
    end
    extra[:program_sessions] = lambda do |program|
      sessions = []
      program.sessions.each do |sesh|
        item = api_attributes(sesh)
        item[:location] = api_attributes(sesh.location)
        item[:links] = makelinks(%w(classes))
        docs = []
        sesh.document_references.each do |docref|
          doc = docref.document
          if doc
            docs << {
              :name => doc.CDM_DocName,
              :href => url(Document.doc(doc.CDM_DocId, doc.CDM_DocName, settings.servers)),
              :status => docref.ACD_STATUS,
              :branchId => doc.CDM_BranchCode
            }
          end
        end
        item[:documents] = docs
        sessions << item
      end
      sessions
    end

  end
  render_index(@programs, Program, extra, render_full)
end

- (Object) get(/<api version>/<associationid>/families/<familyid>/receipts/<receiptid>/questionaire)

Returns a questionnaire applicable for use with a receipt ID. All fields are returned and if the receipt has answers for the questionnaire it will also return the answers. Answers are blank if they are not available.



13
14
15
# File 'app/routes/questionnaires.rb', line 13

get %r{^/v#{settings.version}/\d+/receipts/[^/]+?/questionnaire(\?.*)?$} do
  @questionnaire = @the_receipt.get_questionnaire
end

- (Object) get("/<api version>/<association id>/receipts/<receipt id>") - (Object) get("/<api version>/<association id>/gift_cards/<gift card id>/receipts/<receipt id>") - (Object) get("/<api version>/<association id>/members/<member id>/receipts/<receipt id>")

Describes a receipt.

Extra Information Returned:

  • :pnref

    CCPNRefNo if a Credit Card Transaction

  • :isPrintable

    if receipt is printable

  • :subtotal

    of receipt

  • :credits

    of receipt

  • :salesTax

    sales_tax applicable to receipt

  • :giftCards

    gift_cards information

  • :nsfStatus

    nsf_status of receipt

  • :links

    to transactions



475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
# File 'app/routes/receipts.rb', line 475

get %r{^/v#{settings.version}/\d+((/families/[^/]+)?/members/[^/]+)?(/gift_cards/\d+)?/receipts/\d+(\?.*)?$} do
  Receipt.preload(@receipt.id)
  extra =
    { :pnref => @receipt.credit_card_transaction ? @receipt.credit_card_transaction.CCPNRefNo : '',
      :isPrintable => @receipt.printable?,
      :rcptInProcess => @receipt.RcptInProcess?,
      :subtotal => @receipt.subtotal.to_f,
      :credits => @receipt.credits,
      :salesTax => @receipt.sales_tax,
      :giftCards => @receipt.gift_cards,
      :nsfStatus => @receipt.nsf_status,
      :links => makelinks(%w[transactions]) }
  extra.merge!(:creditCardNumber => @receipt.credit_card_transaction.CCReportCCNo) if @receipt.credit_card_transaction
  render_show(@receipt, extra)
end

- (JSON, HTML) get("/<api version>/<association id>/receipts") - (JSON, HTML) get("/<api version>/<association id>/gift_cards/<gift card id>/receipts") - (JSON, HTML) get("/<api version>/<association id>/members/<member id>/receipts")

Lists receipts. Optionally filters by gift card or member. test.

Overloads:

  • - (JSON, HTML) get("/<api version>/<association id>/receipts")

    Lists all Receipts by association. Not sure if it should be used often as the burden on the DB is high. Mostly you can find what you need in the other overloads or by member's receipts.

  • - (JSON, HTML) get("/<api version>/<association id>/gift_cards/<gift card id>/receipts")

    Lists all Receipts by Gift Card Id. Pass he gift_card_id

  • - (JSON, HTML) get("/<api version>/<association id>/members/<member id>/receipts")

    Lists all receipts by Member. Pass the member_id

Parameters:

  • printable

    returns all printable reciepts. Do not use on the Association level route (i.e., /v.2/10/receipts?printable=)

Returns:

  • (JSON)

    of all receipts

  • (HTML)

    of all receipts when in a browser



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'app/routes/receipts.rb', line 42

get %r{^/v#{settings.version}/\d+((/families/[^/]+)?/members/[^/]+)?(/gift_cards/\d+)?/receipts(\?.*)?$} do
  @receipts = @receipts.printable if params.has_key?('printable')
  if params.has_key?('startDate') && @receipts.present?
    dates = params[:startDate].split(/,/)
    @receipts =
      if dates.size == 1
        @receipts.starting_after(DateTime.parse(dates[0]))
      else
        @receipts.starting_between(DateTime.parse(dates[0]),DateTime.parse(dates[1]))
      end
  end
  if params.has_key?('endDate') && @receipts.present?
    dates = params[:endDate].split(/,/)
    @receipts =
      if dates.size == 1
        @receipts.ending_before(DateTime.parse(dates[0]))
      else
        @receipts.ending_between(DateTime.parse(dates[0]),DateTime.parse(dates[1]))
      end
  end
  extras = {
    :isPrintable => lambda {|receipt| receipt.printable?},
    :creditCardNumber => lambda {|receipt| receipt.credit_card_transaction.CCReportCCNo if receipt.credit_card_transaction},
    :rcptInProcess => lambda { |receipt| receipt.RcptInProcess? }
  }
  render_index(@receipts, Receipt, extras)
end

- (Object) get("/<api version>/<association id>/scans") - (Object) get("/<api version>/<association id>/branches/<branch id>/scans") - (Object) get("/<api version>/<association id>/members/<member id>/scans")



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'app/routes/scans.rb', line 39

get %r{^/v#{settings.version}/\d+(/branches/\d+|(/families/[^/]+)?/members/[^/]+)?/scans(\?.*)?$} do
  if params.has_key?('startDate') && params.has_key?('endDate')
    @scans = @scans.where("scanTime between ? AND ?", DateTime.parse(params['startDate']), DateTime.parse(params['endDate']))
  elsif params.has_key?('startDate')
    @scans = @scans.where("scanTime > ?", DateTime.parse(params['startDate']))
  elsif params.has_key?('endDate')
    @scans = @scans.where("scanTime < ?", DateTime.parse(params['endDate']))
  end

  @scans = @scans.includes(:result, :station, :vac_member) # if @scans.present?
  @scans = @scans.order("scanTime DESC")
  @scans = @scans.limit(@parsed_request.limit).offset(@parsed_request.offset)

  render_index(@scans, Scan,
    { :branchId => lambda {|scan| scan.station.branchCode},
      :location => lambda {|scan| scan.station.name},
      :result => lambda {|scan| scan.result.result},
      :memberId => lambda {|scan| scan.vac_member && scan.vac_member.mid_pid} })
end

- (Object) get("/<api version>/<association id>/schedules/<schedule id>") - (Object) get("/<api version>/<association id>/camps/<camp id>/schedules/<schedule id>") - (Object) get("/<api version>/<association id>/childcares/<childcare id>/schedules/<schedule id>") - (Object) get("/<api version>/<association id>/camp_sessions/<camp session id>/schedules/<schedule id>")

Describes a schedule.

Parameters:

  • memberId

    show the fee for the given member



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'app/routes/schedules.rb', line 133

get %r{^/v#{settings.version}/\d+(/branches/\d+)?((/seasons/\d+)?/camps/\d+)?(/camp_sessions/\d+)?(/childcares/\d+)?/schedules/\d+(\?.*)?$} do
  Schedule.preload(@schedule.id)
  schedule_detail = settings.cache.fetch("#{@association.cache_key}_schedule_#{@schedule.id}_detail") do
    @schedule.detail
  end
  schedule_detail_days = settings.cache.fetch("#{@association.cache_key}_schedule_#{@schedule.id}_detail_days") do
    schedule_detail.days
  end
  extra =
    { :vacancies => @schedule.vacancies,
      :name => schedule_detail.cc_po_Name,
      :minDeposit => @schedule.min_deposit,
      :memberFee => @schedule.member_fee,
      :nonMemberFee => @schedule.non_member_fee,
      :programMemberFee => @schedule.program_member_fee,
      :numberOfDaysToSchedule => schedule_detail.cc_po_Number_of_Days || -1,
      :allowedDays => (schedule_detail_days.select{|d| d.cc_pod_Status == 1}.map{|d| d.cc_pod_dow} rescue []),
      :type => @schedule.type,
      :schedule => schedule_detail_days.map {|day| api_attributes(day)} }
  if @schedule.session
    extra[:campId] = @schedule.session.CC_PS_CC_PROG_ID
  else
    extra[:childcareId] = @schedule.cc_apo_prog_id
  end
  extra[:fee] = @schedule.fee(params[:memberId]) if params.has_key?('memberId')
  render_show(@schedule, extra)
end

- (Object) get("/<api version>/<association id>/schedules") - (Object) get("/<api version>/<association id>/branches/<branch id>/schedules") - (Object) get("/<api version>/<association id>/camps/<camp id>/schedules") - (Object) get("/<api version>/<association id>/childcares/<childcare id>/schedules") - (Object) get("/<api version>/<association id>/camp_sessions/<camp session id>/schedules")

Lists all schedules. Optionally returns only schedules for a given camp, camp session, or childcare.

Query Parameters

  • keyword: searches for schedules using the given query. Will recognize dates, times, program descriptions, category descriptions, or branch names.
  • memberId: show fees for the given member
  • age: search for schedules available to a given age. Accepts a comma-separated range of ages (such as "4,17") or a single value
  • months: specify to search for age in months, not years
  • day: show only schedules that meet on the given days. Accepts a string contaning a combination of the following letters (any order is valid):
    • 'M': Monday
    • 'T': Tuesday
    • 'W': Wednesday
    • 'H': Thursday
    • 'F': Friday
    • 'S': Saturday
    • 'U': Sunday
  • startTime: show only schedules that start during the given time range. Example: startTime=11:00,14:00
  • startDate: show only schedules that start on or after the given date. If a range is given, show only schedules that start on a date within the given range. Valid examples:
    • startDate=2012-10-05
    • startDate=2012-10-15,2012-12-1
  • endDate: show only schedules that end on or before the given date. If a range is given, show only schedules that end on a date within the given range. Valid examples:
    • endDate=2012-10-05
    • endDate=2012-10-15,2012-12-1
  • current: search for schedules that are currently available
  • active: search for active schedules
  • enabled: search for enabled schedules
  • ssp: search for ssp-available schedules


74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'app/routes/schedules.rb', line 74

get %r{^/v#{settings.version}/\d+(/branches/\d+)?((/seasons/\d+)?/camps/\d+)?(/camp_sessions/\d+)?(/childcares/\d+)?/schedules(\?.*)?$} do
  if params.has_key?('day')
    i = 0
    days = %w[U M T W H F S].inject([]) do |arr,day|
      arr << Date::DAYNAMES[i] if params[:day].index(day)
      i += 1
      arr
    end
    @schedules = @schedules.on_days(days)
  end
  if params.has_key?('startTime')
    time = params[:startTime].split(/,/)
    @schedules = @schedules.during(time[0], time[1])
  end
  if params.has_key?('startDate')
    dates = params[:startDate].split(/,/)
    @schedules =
      if dates.size == 1
        @schedules.starting_after(DateTime.parse(dates[0]))
      else
        @schedules.starting_between(DateTime.parse(dates[0]),DateTime.parse(dates[1]))
      end
  end
  if params.has_key?('endDate')
    dates = params[:endDate].split(/,/)
    @schedules =
      if dates.size == 1
        @schedules.ending_before(DateTime.parse(dates[0]))
      else
        @schedules.ending_between(DateTime.parse(dates[0]),DateTime.parse(dates[1]))
      end
  end
  @schedules = @schedules.search(params[:keyword]) if params.has_key?('keyword')
  @schedules = @schedules.for_age(params[:age], params.has_key?('months')) if params.has_key?('age')
  @schedules = @schedules.current if params.has_key?('current')
  @schedules = @schedules.ssp if params.has_key?('ssp')
  @schedules = @schedules.active if params.has_key?('active')
  @schedules = @schedules.enabled if params.has_key?('enabled')
  extra = {
    :name => lambda {|schedule| schedule.detail.cc_po_Name},
    :minDeposit => lambda {|schedule| schedule.min_deposit},
    :memberFee => lambda {|schedule| schedule.member_fee},
    :nonMemberFee => lambda {|schedule| schedule.non_member_fee},
    :programMemberFee => lambda {|schedule| schedule.program_member_fee},
    :vacancies => lambda {|schedule| schedule.vacancies},
  }
  extra[:fee] = lambda {|schedule| schedule.fee(params[:memberId])} if params.has_key?('memberId')
  render_index(@schedules, Schedule, extra)
end

- (Object) get("/<api version>/<association id>/seasons/<season id>") - (Object) get("/<api version>/<association id>/branches/<branch id>/seasons/<season id>")

Describes a season.



36
37
38
# File 'app/routes/seasons.rb', line 36

get %r{^/v#{settings.version}/\d+(/branches/\d+)?/seasons/\d+(\?.*)?$} do
  render_show(@season, :links => makelinks(%w[camps]))
end

- (Object) get("/<api version>/<association id>/seasons") - (Object) get("/<api version>/<association id>/branches/<branch id>/seasons")

Lists all seasons. Optionally filters by branch.

Query Parameters

  • keyword: search for season by keyword


26
27
28
29
# File 'app/routes/seasons.rb', line 26

get %r{^/v#{settings.version}/\d+(/branches/\d+)?/seasons(\?.*)?$} do
  @seasons = @seasons.search(params[:keyword]) if params.has_key?('keyword')
  render_index(@seasons, Season)
end

- (Object) get("/<api version>/<association id>/subsidies") - (Object) get("/<api version>/<association id>/members/<member id>/subsidies")

Lists all subsidies. Optionally filters by member. Use parameters to restrict the list to show only subsidies for programs or memberships that are active and current as of now. A subsidy can contain either an amount or a percentage. Fixed amounts are possible only for memberships.

Query Parameters

  • type: only return enabled subsidies of the specified type. Can be one of: membership, camp, program
  • ssp: show only subsidies available to the ssp
  • staff: show only subsidies available to the staff portal
  • active: show only subsidies that are marked as active
  • current: return only subsidies that are currently available
  • membershipId: also return custom subsidies applicable to the given membership


42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'app/routes/subsidies.rb', line 42

get %r{^/v#{settings.version}/\d+((/families/[^/]+)?/members/[^/]+)?/subsidies(\?.*)?$} do
  mem = Membership.find(params['membershipId']) if params.has_key?('membershipId')
  filters = []
  case params[:type]
    when "program" then filters << :for_programs
    when "membership" then filters << :for_memberships
    when "camp" then filters << :for_camps
  end if params.has_key?('type')
  @subsidies = @subsidies.current if params.has_key?('current')
  %w[ssp staff active].each {|str| filters << str.to_sym if params.has_key?(str)}
  filters.each do |filter|
    if mem
      @subsidies = @subsidies.send(filter, mem)
    else
      @subsidies = @subsidies.send(filter)
    end
  end
  extras =
    { :active => lambda {|subsidy| subsidy.active},
      :awardNumber => lambda {|subsidy| subsidy.award.SSA_AwardNo},
      :primaryContact => lambda {|subsidy| subsidy.award.SSA_PrimaryContact},
      :starts => lambda {|subsidy| subsidy.award.SSA_StartDate},
      :expires => lambda {|subsidy| subsidy.award.SSA_ExpirationDate},
      :entered => lambda {|subsidy| subsidy.award.SSA_EnteredDate},
      :note => lambda {|subsidy| subsidy.award.SSA_Note},
      :type => lambda {|subsidy| subsidy.type.SITM_ItemType} }
  s = @subsidies.joins(:category1)
  @subsidies =
    if params.has_key?('membershipId')
      extras.merge!(
        :percent => lambda {|subsidy| subsidy.percent(mem)},
        :amount => lambda {|subsidy| subsidy.amount(mem)})
      s + @subsidies.custom(mem)
    else
      extras.merge!(
        :percent => lambda {|subsidy| subsidy.percent},
        :amount => lambda {|subsidy| subsidy.amount})
      s
    end
  render_index(@subsidies, Subsidy, extras)
end

- (Object) get("/<api version>/<association id>/subsidies/<subsidy id>") - (Object) get("/<api version>/<association id>/members/<member id>/subsidies/<subsidy id>")

Describes a subsidy. * membershipId: if this is a custom membership subsidy, display amount or percent for this membership



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'app/routes/subsidies.rb', line 91

get %r{^/v#{settings.version}/\d+((/families/[^/]+)?/members/[^/]+)?/subsidies/\d+(\?.*)?$} do
  extra =
    { :awardNumber => @subsidy.award.SSA_AwardNo,
      :active => @subsidy.active,
      :primaryContact => @subsidy.award.SSA_PrimaryContact,
      :starts => @subsidy.award.SSA_StartDate,
      :expires => @subsidy.award.SSA_ExpirationDate,
      :entered => @subsidy.award.SSA_EnteredDate,
      :note => @subsidy.award.SSA_Note,
      :type => @subsidy.type.SITM_ItemType,
      :category => api_attributes(@subsidy.category) }
  if params.has_key?('membershipId')
    mem = Membership.find(params['membershipId'])
    extra.merge!(
      :percent => @subsidy.percent(mem),
      :amount => @subsidy.amount(mem) )
  else
    extra.merge!(
      :percent => @subsidy.percent,
      :amount => @subsidy.amount )
  end
  render_show(@subsidy, extra)
end

- (Object) get("/<api version>/<association id>/transactions/<transaction id>") - (Object) get("/<api version>/<association id>/gift_cards/<gift card id>/transactions/<transaction id>") - (Object) get("/<api version>/<association id>/receipts/<receipt id>/transactions/<transaction id>") - (Object) get("/<api version>/<association id>/members/<member id>/transactions/<transaction id>") - (Object) get("/<api version>/<association id>/families/<family id>/transactions/<transaction id>")

Describes a transaction.



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'app/routes/transactions.rb', line 104

get %r{^/v#{settings.version}/\d+((\/families\/[^\/]+)?)?(\/members\/[^\/]+)?((/gift_cards/\d+)?/receipts/\d+)?/transactions/\d+(\?.*)?$} do
  Transaction.preload(@transaction.id)
  extra = Hash.new
  extra[:links] = Array.new
  if @transaction.pledge
    extra[:links] <<
      { :content => "Pledge",
        :href => "/v#{settings.version}/#{@association.db.id}/pledges/#{@transaction.pledge.id}",
        :rel => "pledge" }
  end
  if @transaction.course
    extra[:links] <<
      { :content => "Class",
        :href => "/v#{settings.version}/#{@association.db.id}/classes/#{@transaction.course.id}",
        :rel => "class" }
  end
  if @transaction.membership_fee
    extra[:membershipFee] = api_attributes @transaction.membership_fee
    extra[:links] <<
      { :content => "Membership",
        :href => "/v#{settings.version}/#{@association.db.id}/memberships/#{@transaction.membership_fee.membership.id}",
        :rel => "membership" }
  end
  if @transaction.counter_item
    extra[:links] <<
      { :content => "Counter Item",
        :href => "/v#{settings.version}/#{@association.db.id}/classes/#{@transaction.counter_item.id}",
        :rel => "counter_item" }
  end
  if @transaction.invoice_detail
    extra[:invoiceDetail] = api_attributes(@transaction.invoice_detail)
    extra[:links] <<
      { :content => "Invoice",
        :href => "/v#{settings.version}/#{@association.db.id}/invoices/#{@transaction.invoice_detail.invoice.id}",
        :rel => "membership" }
  end
  if @transaction.camp_payment && !@transaction.camp_payment.posting.enrollment.nil?
    extra[:scheduleId] = @transaction.camp_payment.posting.enrollment.schedule.id
    extra[:links] <<
      { :content => "Schedule",
        :href => "/v#{settings.version}/#{@association.db.id}/schedules/#{extra[:scheduleId]}",
        :rel => "schedule" }
  end
  if @transaction.childcare_payment && !@transaction.childcare_payment.posting.enrollment.nil? && @transaction.childcare_payment.posting.enrollment.schedule.present?
    extra[:childcareId] = @transaction.childcare_payment.posting.enrollment.schedule.cc_apo_prog_id
    extra[:links] <<
      { :content => "Schedule",
        :href => "/v#{settings.version}/#{@association.db.id}/schedules/#{extra[:childcareId]}",
        :rel => "schedule" }
  end
  extra[:date] = @transaction.receipt.RcptDate
  extra[:receiptId] = @transaction.receipt.id
  extra[:invoiceId] = @transaction.invoice_detail.invoiceId if @transaction.invoice_detail
  extra[:credits] = @transaction.credits
  extra[:deposits] = @transaction.get_deposit_value
  extra[:subsidies] = @transaction.subsidies
  extra[:subtotal] = @transaction.subtotal
  extra[:paid] = @transaction.paid.to_f
  extra[:fees] = @transaction.fees
  extra[:salesTax] = @transaction.sales_tax
  extra[:outstandingBalance] = @transaction.outstanding_balance
  extra[:category] = @transaction.type.ReceiptHeader
  extra[:receiptType] = @transaction.receipt_type
  extra[:isOutstanding] = @transaction.outstanding?
  extra[:isServiceCharge] = @transaction.service_charge?
  extra[:isValid] = @transaction.is_valid?

  render_show(@transaction, extra)
end

- (Object) get("/<api version>/<association id>/transactions") - (Object) get("/<api version>/<association id>/gift_cards/<gift card id>/transactions") - (Object) get("/<api version>/<association id>/receipts/<receipt id>/transactions") - (Object) get("/<api version>/<association id>/members/<member id>/transactions") - (Object) get("/<api version>/<association id>/families/<family id>/transactions")

Lists transactions. Optionally filters by member, gift card, or receipt.

Query Parameters

  • type: only return transactions of the specified type. Can be one of: [ program, membership, donation, childcare, camp, purchase ]
  • from: only return transactions after the specified date.
  • to: only return transactions before the specified date.
  • valid: only return transactions marked as valid


50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'app/routes/transactions.rb', line 50

get %r{^/v#{settings.version}/\d+(/families/[^/]+)?(/members/[^/]+)?((/gift_cards/\d+)?/receipts/\d+)?/transactions(\?.*)?$} do
  if params.has_key?('type') && ["valid_programs", "program", "membership", "donation", "childcare", "camp", "purchase"].include?(params[:type])
    @transactions = @transactions.send(params[:type])
    @is_program = params[:type] == "valid_programs"
  end
  tz = Customizations.instance.TimeZone.to_s
  @transactions = @transactions.from_date(DateTime.parse(params[:from]).new_offset(tz)) if params.has_key?('from')
  @transactions = @transactions.to_date(DateTime.parse(params[:to]).new_offset(tz)) if params.has_key?('to')
  @transactions = @transactions.includes(:invoice_detail)
  @transactions = @transactions.valid if params.has_key?('valid')
  extras = {:isValid => lambda{|transaction| transaction.is_valid?},
    :type => lambda{|transaction| transaction.type.TxnType},
    :isOutstanding => lambda{|transaction| transaction.outstanding?},
    :isServiceCharge => lambda{|transaction| transaction.service_charge?},
    :date => lambda{|transaction| transaction.receipt.RcptDate},
    :receiptId => lambda{|transaction| transaction.receipt.id},
    :invoiceId => lambda{|transaction| transaction.invoice_detail ? transaction.invoice_detail.invoiceId : nil},
    :membershipId => lambda{|transaction| transaction.membership_fee ? transaction.membership_fee.ysysMemId : nil},
    :credits => lambda{|transaction| transaction.credits},
    :deposits => lambda{|transaction| transaction.get_deposit_value},
    :subsidies => lambda{|transaction| transaction.subsidies.to_f},
    :subtotal => lambda{|transaction| transaction.subtotal.to_f},
    :paid => lambda{|transaction| transaction.paid.to_f},
    :fees => lambda{|transaction| transaction.fees},
    :category => lambda{|transaction| transaction.type.ReceiptHeader},
    :salesTax => lambda{|transaction| transaction.sales_tax},
    :outstandingBalance => lambda{|transaction| transaction.outstanding_balance}}
  if @is_program.present?
    extras[:program_name] = lambda{|tran| tran.course.program_session.program.PM_ShortDescription}
    # extras[:minAge] = lambda{}
    # extras[:maxAge] = lambda{}
    # extras[:image] =  lambda{}
    # extras[:memberName] = lambda{}
  end
  render_index(@transactions, Transaction, extras)
end

- (JSON) get(/<api version>/<associationid>/user_masters/<user_masterid>)

Returns the user_master record based on it's id and on the member id

Returns:

  • (JSON)

    Returns the user_master record based on it's id and on the member id



74
75
76
77
# File 'app/routes/user_masters.rb', line 74

get %r{^/v#{settings.version}/\d+/user_masters/([\w-]+)?$} do |the_id|
  @user_master = UserMaster.where(:UserId => the_id).first
  render_show(@user_master)
end

- (JSON) get(/<api version>/<associationid>/user_masters)

Returns all user master records for the association

Returns:

  • (JSON)

    all user master records for the association



6
7
8
9
# File 'app/routes/user_masters.rb', line 6

get %r{^/v#{settings.version}/\d+/user_masters(\?.*)?$} do
  @user_masters = UserMaster.where(:active => true).where(:accountLocked => false)
  render_index(@user_masters, UserMaster)
end

- (Object) post(/<api version>/<associationid>/members/<memberid>/allergy_infos)

Parameters:

  • allergies

    will take up to 200 characters to describe their allergies

  • medications

    will take up to 200 chars to describe medications they take

  • health_concerns

    will take up to 500 chars on health concerns

  • allergy_notes

    will take up to 500 chars for additional allergy notes



29
30
31
32
# File 'app/routes/allergy_info.rb', line 29

post %r{^/v#{settings.version}/\d+/members/[^/]+?/allergy_infos(\?.*)?$} do
  add_headers
  handle_allergy_info_insert(params)
end

- (Object) post(/<api version>/<associationid>/members/<memberid>/bus_infos)



30
31
32
33
# File 'app/routes/bus_infos.rb', line 30

post %r{^/v#{settings.version}/\d+/members/[^/]+?/bus_infos(\?.*)?$} do
  add_headers
  handle_bus_info_insert(params)
end

- (Object) post(/<api version>/<associationid>/members/<memberid>/emergency_contacts)



24
25
26
27
# File 'app/routes/emergency_contacts.rb', line 24

post %r{^/v#{settings.version}/\d+/members/[^/]+?/emergency_contacts(\?.*)?$} do
  add_headers
  handle_emergency_contact_insert(params)
end

- (Object) post("/<api version>/<association id>/families")

Adds a family.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'app/routes/families.rb', line 43

post %r{^/v#{settings.version}/\d+/(family_connections|families)(\?.*)?$} do
  data = request.content_type =~ /json/ ? JSON.parse(request.body.read) : params
  %w[captures splat _method].each {|field| data[field] && data.delete(field)}
  data = model_attributes(:families, data)
  add_headers
  # invalidate family cache
  # ToDone? - invalidate all members of the cache
  dirty_cache
  Family.transaction do
    family = Family.new(data)
    if !family.valid? || !family.save
      message = family.errors.full_messages.join(". ")
      halt_with_error(400, message)
    else
      headers "X-Family-ID" => family.id
      headers "X-Family-Connection-ID" => family.id
      halt 201
    end
  end
  halt_with_error(500, "Need a better error message...")
end

- (Object) post(/<api version>/<associationid>/members/<memberid>/immunizations)

Note that this POST route probably won't be used.



17
18
19
20
# File 'app/routes/immunizations.rb', line 17

post %r{^/v#{settings.version}/\d+/members/[^/]+?/immunizations(\?.*)?$} do
  add_headers
  handle_immunization_insert(params)
end

- (Object) post(/<api version>/<associationid>/members/<memberid>/medical_contacts)



22
23
24
25
# File 'app/routes/medical_contacts.rb', line 22

post %r{^/v#{settings.version}/\d+/members/[^/]+?/medical_contacts(\?.*)?$} do
  add_headers
  handle_medical_contact_insert(params)
end

- (JSON) post("/<api version>/<association id>/families/<family id>/members")

Creates a new member.

Pass all standard fields as returned by the GET method. In order to save custom field values for a member, pass custom fields as:

{ ..., "customFieldValues" : { "<field id>": "<data>", "<field id>": "<data>", ... }, ... }

where:

  • <field id> is the id defined in the customization section of the field definition.
  • <data> is the actual value of the field. Returns a 201 on Success. Returns a 400 if the member information is not valid, or the system couldn't make it a member for some reason. Also, a 500 is returned if the Member object is not created. homePhone workPhone cellPhone emergencyPhone are sanitized to verify it is a proper phonenumber prior to being saved. As is zipcode.

Returns:

  • (JSON)

    of all information regarding the members

See Also:



111
112
113
114
# File 'app/routes/members.rb', line 111

def find_demographic_fields(data)
  potential_demographic_fields = data.keys.select { |k| k =~ /demographics?/i }
  potential_demographic_fields.first
end

- (Object) post("/<api version>/<association id>/families/<family id>/payment_instruments/")

Adds a payment instrument for a family.

Up to 3 payment instruments can be stored for a family. An error will be returned if more payment instruments are attempted to be created.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'app/routes/payment_instruments.rb', line 42

post %r{^/v#{settings.version}/\d+/families/[^/]+/payment_instruments(\?.*)?$} do
  if @family.e_wallets.size >= 3
    halt_with_error(403, "Maximum number of payment instruments reached")
  end
  data = case request.content_type
  when /json/
    json = request.body.read
    logger.debug("Loading json data ")
    logger.debug(json)
    model_attributes(:payment_instruments, JSON.parse(json))
  else
    logger.debug("Loading query parameters ")
    logger.debug(params)
    model_attributes(:payment_instruments, params)
  end
  logger.debug(data.inspect)
  add_headers
  dirty_cache
  ewallet = EWallet.new(:EW_FamilyID => @family.id)
  payment_instrument = ewallet.build_payment_instrument(data)
  if ewallet.save
    headers "X-Payment-Instrument-ID" => payment_instrument.id.to_s
    halt 201
  else
    error_message = payment_instrument.errors.full_messages.join('. ')
    halt_with_error(400, error_message)
  end
end

- (Object) post(/<api version>/<associationid>/members/<memberid>/pickup)



25
26
27
28
# File 'app/routes/pickups.rb', line 25

post %r{^/v#{settings.version}/\d+/members/[^/]+?/pickups(\?.*)?$} do
  add_headers
  handle_pickup_insert(params)
end

- (Object) post(/<api version>/<associationid>/receipts/<receiptid>/questionaire)



20
21
22
23
24
# File 'app/routes/questionnaires.rb', line 20

post %r{^/v#{settings.version}/\d+/receipts/[^/]+?/questionnaire(\?.*)?$} do
  # depending on the questionnaire
  add_headers
  halt 201, "Hello"
end

- (Object) post("/<api version>/<association id>/families/<family id>/receipts")

Adds a receipt.

Returns:

  • 201 on success

Data Paramaters:

  • returnUrl

    The URL to return the user to after making a paypal payment.

  • errorUrl

    The URL to return the user to upon paypal erorr.

  • cancelUrl

    The URL to return the user to if the user cancels the paypal payment.

  • new_memberships

    An array containing information on each new membership transaction. Fields in the array are: * memberId The ID of the person who is being registered for a new membership. * additionalMemberIds An array consisting of the IDs of the additional people to add to the membership. * membershipId The ID of the membership for which the person is registering. * feeIds An array consisting of IDs of membership fees to charge for. * creditAmounts A hash, keyed on membership fees, whose values are the amount of online credit to apply to the given fee.

  • membership_renewals

    An array containing information on each membership renewal. Fields in the array are: * memberId The ID of the person who is renewing their membership. * creditAmounts A hash, keyed on membership fees, whose values are the amount of online credit to apply to the given fee.

  • registrations

    An array containing information on each class or camp registration. Fields in the array are: * memberId The ID of the person who is being registered for a class or camp. * classId The ID of the class for which the person is registering. * amount The amount to apply as a deposit (do not use if paying full amount). * scheduleId The ID of the camp schedule for which the person is registering. * sponsorID The sponsor for the camp registration. Required for camp registrations. * customFieldValues Array consisting of custom field data in the form of key-value pairs, where the keys are the custom field id and the values are the data (either the option id or the input value). * creditAmount Use this amount of online credit.

  • donations

    An array containing information on each donation. Fields in the array are:

    • memberId The ID of the person who is making a donation.
    • appealId The ID of the appeal to which the person is donating.
    • amount The amount of the donation.
    • isPrompt true if the donation originated in the Donation Prompt.
    • creditAmount Use this amount of online credit.
    • comment a comment about the donation e.g., Annual donation for good cause.
    • attributions attributions about the donation e.g., Ashok's Grand Father.
  • ob_payments

    An array containing information on each outstanding balance payment. Fields in the array are: * id The ID of the outstanding balance to pay. * amount The amount to pay. * creditAmount Use this amount of online credit to pay.

  • gift_cards

    An array containing information on gift cards to use. Fields in the array are: * id The gift card id. * pin The gift card PIN number. * amount The amount to apply to the card.

Query Parameters:

  • type

    one of "ssp" or "staff"; must be present

  • express

    flags that this is an express checkout transaction

Http Headers Returned:

  • X-Receipt-Id

    The new receipt ID.

  • X-Total

    The amount to charge the user (including taxes). This should be the same as the sum of all line items displayed to the user.

  • X-Secure-Token

    The secure token to use with PayPal.

  • X-Secure-Token-Id

    The secure token id to use with PayPal.

  • X-Gateway-URL

    The gateway to direct the user to for payment.



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
# File 'app/routes/receipts.rb', line 121

post %r{^/v#{settings.version}/\d+/families/[^/]+/receipts(\?.*)?$} do
  data =
    case request.content_type
    when /json/ then JSON.parse(request.body.read)
    else params
    end

  logger.debug(request.body.read.inspect)
  logger.debug(data.inspect)


  log_hash = {
    :local_time => Time.now,
    :zone_time => Time.zone.now,
    :association_id => @association.id,
  }
  logger.info("receipt generation debugging: " + log_hash.inspect)

  visitor = nil
  receipt = nil
  cust = @association.pay_pal_configuration
  paypal_sanity_check(data, cust) #raises if correct paypal info isn't found. no point continuing
  the_receipts = @family.flush_temporary_transactions(cust)
  if the_receipts.blank?
    Organization.transaction do
      visitor, receipt, primary_member = @family.create_visitor_and_receipt

      data["donations"] && data["donations"].each do |donation|
        appeal = Appeal.find(donation["appealId"])
        member = Member.find(donation["memberId"])
        receipt.add_donation(member, visitor, donation["amount"], donation["creditAmount"], appeal, donation["isPrompt"], donation)
      end
      wait_listed_classes = []
      data["registrations"] && data["registrations"].each do |registration|
        if registration["scheduleId"] && registration["classId"]
          raise "Cannot register for two programs at once."
        else
          # begin
            receipt.handle_registration(registration, visitor)
          # rescue Exception => e
          #   if e == "waitlisted"
          #     the_key = registration["scheduleId"].present? ? {"campId" => registration["scheduleId"]} : {"classId" => registration["classId"]}
          #     wait_listed_classes <<  {"memberId" => registration["memberId"]}.merge(the_key)
          #   end
          # end
        end
      end
      data["membership_renewals"] && data["membership_renewals"].each do |renewal|

        begin
          receipt.handle_membership(renewal, visitor, @association.customizations, true)

        rescue Exception => e
          logger.error(e.inspect)
          halt_with_error(400, e.message)
        end
      end
      data["new_memberships"] && data["new_memberships"].each do |mem|

        begin
          receipt.handle_membership(mem, visitor, @association.customizations, false)
        rescue Exception => e
          logger.error(e.inspect)
          halt_with_error(400, e.message)
        end
      end
      data["ob_payments"] && data["ob_payments"].each do |payment|
        member = nil
        @family.members.all.each do |m|
          if m.balances(payment["id"])
            member = m
            break
          end
        end
        receipt.add_ob_payment(member, visitor, payment["id"], payment["amount"], payment["creditAmount"])
      end

      Receipt.preload(receipt.id)

      data["gift_cards"] && data["gift_cards"].each do |card|
        gift_card = GiftCard.where(:GCM_CardPin => card["pin"]).find(card["id"])
        unless gift_card.balance >= card["amount"]
          raise("Insufficient gift card balance.")
        end
        receipt.apply_gift_card(gift_card, card["amount"])
      end
    end

    tax = receipt.precalc_sales_tax

    amount = receipt.total(tax)

    add_headers
    headers(
      "X-Receipt-Id" => receipt.id.to_s,
      "X-Total"      => amount.to_s,
      "X-Tax"        => tax.to_s,
    )

    if amount > 0.0
      raise "No paypal configuration information, cannot continue." if cust.nil?

      paypal = Paypal.new(cust)

      type =
        case params[:type]
        when "ssp" then "SSP"
        when "staff" then "Staff"
        when "epay" then "Epay"
        when "donate_now" then "DonateNow"
        else halt_with_error(400, "Must specify transaction type.")
        end

      headers("X-Test-Mode" => cust.PayPal_TestMode == 1 ? "true" : "false")
      token = nil
      if params.has_key?('express')
        until token
          begin
            token = paypal.post_express(amount, receipt.id.to_s, data, receipt.transactions)
          rescue Exception => e
            logger.error(e)
          end
        end
        secure_token = token["TOKEN"]
        headers(
                "X-Gateway-URL" => cust.PayPal_ExpressCheckoutURL,
                "X-Token" => secure_token)
      else
        until token
          begin
            #break out secure token into a join table to look up for the applicable receipt id.
            #can we pull the secure token out and use for both, instead of two of these.
            token = paypal.post_with_token(amount, receipt.id.to_s, data)
          rescue Exception => e
            logger.error(e)
          end
        end

        secure_token = token["SECURETOKEN"]
        secure_token_id = token["SECURETOKENID"]
        headers(
                "X-Secure-Token" => secure_token,
                "X-Secure-Token-Id" => secure_token_id,
                "X-Gateway-URL" => cust.PayPal_HostedCheckoutURL)
      end
      RestClient.log.debug(token)
      trans = CreditCardTransaction.create(
                                           :CcTokenNo => visitor.id,
                                           :CcTxnDate => receipt.RcptDate,
                                           :MemberId => @family.primary_member.id,
                                           :CCResult => -999,
                                           :Cc_MMV_ID => 3,
                                           :PayPalTokenNo => secure_token,
                                           :PayPalTokenRequestId => params.has_key?('express') ? "" : secure_token_id,
                                           :PayPalTransactionRequestId => "",
                                           :CCExpDate => "",
                                           :CCStatus => -1,
                                           :CC_IsOfflinePayment => 0,
                                           :PayPalCoRelationId => params.has_key?('express') ? token["CORRELATIONID"] : "",
                                           :PayPalTokenStatus => 1,
                                           :CCFees => amount)
      receipt.CcTxnId = trans.id
      receipt.save

      dirty_cache
    else
      receipt.update_attributes(:CcTxnId => 0, :RcptPaymentMode => 'Cash')
      receipt.finalize(Branch.find(@association.Y_Branch), visitor.id)
      dirty_cache
    end
  halt 201 #, {'Content-Type' => 'application/json'}, {"waitListedClasses" => wait_listed_classes}.to_json
  else
    headers("X-Test-Mode" => cust.PayPal_TestMode == 1 ? "true" : "false")
    #         "Access-Control-Allow-Headers"  => "X-Authentication-Token, Content-Type, X-Gateway-URL, X-Receipt-Id, X-Token, X-Test-Mode, X-Secure-Token,  X-Secure-Token-Id, X-Member-ID, X-Family-ID, X-Family-Connection-ID, X-Tax, X-Payment-Instrument-ID, Error-Message, X-Total, X-Paypal-Response",
    #         "Access-Control-Expose-Headers" => "X-Authentication-Token, Content-Type, X-Gateway-URL, X-Receipt-Id, X-Token, X-Test-Mode, X-Secure-Token,  X-Secure-Token-Id, X-Member-ID, X-Family-ID, X-Family-Connection-ID, X-Tax, X-Payment-Instrument-ID, Error-Message, X-Total, X-Paypal-Response"
    #         )

    handle_unfinalized_receipts(the_receipts, cust) #helper
    dirty_cache
    halt 204
  end
end

- (JSON) post(/<api version>/<associationid>/user_masters)

Returns 200 on success

Parameters:

  • UserId

    must appear as this, or system will not save.

  • password

    if you are changing the password. notice the lower case!

  • firstName

    First Name of person

  • lastName

    Last Name of person

  • lastChange
    • not used really yet
  • active

    is person active

  • branchCode

    The Branch Code the person belongs to

  • accountLocked

    1 or 0 to denote if this account should be locked. probably not used in POST

  • accountLockedTime

    time to lock account

  • email

    Email of person

  • xVoicePassword

    used to set XVoice Password

  • employeeId

    Employee Id

  • dateHired

    The date person was hired

  • employeeType

    options include: "Full Time", "Part Time",

  • payMethod

    options include: "Hourly", "Salary"

Returns:

  • (JSON)

    200 on success



29
30
31
32
33
34
35
36
37
38
39
# File 'app/routes/user_masters.rb', line 29

post %r{^/v#{settings.version}/\d+/user_masters(\?.*)?$} do
  params = request.content_type =~ /json/ ? JSON.parse(request.body.read) : params
  data = model_attributes(:user_masters, params)
  @user_master = UserMaster.new(data)
  @user_master.UserId = data["UserId"]
  if @user_master.save
    halt 200
  else
    halt_with_error("Errors are: #{@user_master.errors.inspect}")
  end
end

- (Object) put(/<api version>/<associationid>/members/<MemberId>/allergy_infos)

Parameters:

  • allergies

    will take up to 200 characters to describe their allergies

  • medications

    will take up to 200 chars to describe medications they take

  • health_concerns

    will take up to 500 chars on health concerns

  • allergy_notes

    will take up to 500 chars for additional allergy notes



40
41
42
# File 'app/routes/allergy_info.rb', line 40

put %r{^/v#{settings.version}/\d+/members/[^/]+?/allergy_infos/(\d+)?$} do |the_id|
  handle_allergy_info_insert(params, the_id)
end

- (Object) put(/<api version>/<associationid>/members/<MemberId>/bus_infos)



37
38
39
# File 'app/routes/bus_infos.rb', line 37

put %r{^/v#{settings.version}/\d+/members/[^/]+?/bus_infos/(\d+)?$} do |the_id|
  handle_bus_info_insert(params, the_id)
end

- (Object) put(/<api version>/<associationid>/members/<MemberId>/emergency_contacts)



31
32
33
# File 'app/routes/emergency_contacts.rb', line 31

put %r{^/v#{settings.version}/\d+/members/[^/]+?/emergency_contacts/(\d+)?$} do |the_id|
  handle_emergency_contact_insert(params, the_id)
end

- (Object) put("/<api version>/<association id>/families/<family id>")

Updates a family.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'app/routes/families.rb', line 94

put %r{^/v#{settings.version}/\d+/(family_connections|families)/[^/]+(\?.*)?$} do
  data = request.content_type =~ /json/ ? JSON.parse(request.body.read) : params
  @family.updating_the_password_if_different(data.delete("password"))
  %w[captures splat _method].each {|field| data[field] && data.delete(field)}
  data = model_attributes(:families, data)

  # invalidate family cache
  dirty_cache
  if @family.update_attributes(model_attributes(:families, data))
    case request.preferred_type(['text/html', 'application/json'])
    when /html/
      redirect "#{request.path}"
    else
      halt 204
    end
  else
    message = @family.errors.full_messages.join(". ")
    halt_with_error(message)
  end
end

- (Object) put(/<api version>/<associationid>/members/<MemberId>/immunizations)



26
27
28
# File 'app/routes/immunizations.rb', line 26

put %r{^/v#{settings.version}/\d+/members/[^/]+?/immunizations/(\d+)?$} do |the_id|
  handle_immunization_insert(params, the_id)
end

- (Object) put(/<api version>/<associationid>/members/<MemberId>/medical_contacts)



29
30
31
# File 'app/routes/medical_contacts.rb', line 29

put %r{^/v#{settings.version}/\d+/members/[^/]+?/medical_contacts/(\d+)?$} do |the_id|
  handle_medical_contact_insert(params, the_id)
end

- (JSON, HTML) put("/<api version>/<association id>/members/<member id>")

Updates a member.

Returns a 201 & clears the cache on success or a 500 if the Member object is not updated. homePhone workPhone cellPhone emergencyPhone are sanitized to verify it is a proper phonenumber prior to being saved.

Returns:

  • (JSON)

    of all information regarding the members

  • (HTML)

    if you are on the browser looking at this route



270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'app/routes/members.rb', line 270

put %r{^/v#{settings.version}/\d+(/(families|family_connections)/[^/]+)?/members/[^/]+(\?.*)?$} do
  data = request.content_type =~ /json/ ? JSON.parse(request.body.read) : params
  custom_fields = data.delete("customFieldValues")
  demographic_fields = data.delete(find_demographic_fields(data))
  logger.debug(demographic_fields.inspect) unless demographic_fields.blank?
  %w[captures splat _method].each {|field| data[field] && data.delete(field)}
  data = model_attributes(:members, data)
  !data["address_attributes"] && data["address_attributes"] = Hash.new
  data["address_attributes"]["id"] = @member.address.id
  logger.debug(data.inspect)

  %w[homePhone workPhone cellPhone emergencyPhone].each do |phone|
    data[phone] = phoneify(data[phone], phone == 'workPhone', true) if data.has_key?(phone)
  end
  add_headers
  # invalidate family and member caches
  Member.transaction do
    if @member.update_attributes(data)
      @member.insert_custom_fields(custom_fields) if custom_fields.present?
      if demographic_fields.present?
        demo_fields = demographic_fields.is_a?(Hash) ? demographic_fields : json_array_to_params_hash(demographic_fields)
        demographic = @member.create_or_update_demographic(model_attributes(:demographics, demo_fields))
      end
      case request.preferred_type(['text/html', 'application/json'])
      when /html/
        dirty_cache
        redirect "#{request.path}"
      else
        dirty_cache
        halt 201
      end
    else
      throw @member.errors.full_messages.join(". ")
    end
  end
  halt_with_error(500, "Need better message...")
end

- (JSON, HTML) get("/<api version>/<association id>/families/<family id>/peding_receipt/<receipt id>")

Used to update a receipt that is being sent to PayPal. When PayPal returns response we set back to another status.

Returns:

  • (JSON)

    200

  • (HTML)

    200



40
41
42
43
# File 'app/routes/pending_receipts.rb', line 40

put %r{^/v#{settings.version}/\d+(/families/[^/]+)?/pending_receipt/\d+(\?.*)?$} do
  Receipt.execute_procedure(:NVC_SetResetRcptInProcess, @receipt.id, 1)
  halt 200
end

- (Object) put(/<api version>/<associationid>/members/<MemberId>/pickup)



32
33
34
# File 'app/routes/pickups.rb', line 32

put %r{^/v#{settings.version}/\d+/members/[^/]+?/pickups/(\d+)?$} do |the_id|
  handle_pickup_insert(params, the_id)
end

- (Object) get(/<api version>/<associationid>/members/<MemberId>/receipts/<ReceiptId>/transactions/<TransactionId>/questionaire)



28
29
30
# File 'app/routes/questionnaires.rb', line 28

put %r{^/v#{settings.version}/\d+/receipts/[^/]+?/questionnaire(\?.*)?$} do
  halt 201, "Hello"
end

- (JSON) put("/<api version>/<association id>/receipts") - (JSON) put("/<api version>/<association id>/families/<family id>/receipts")

Marks a receipt as paid.

Returns:

  • (JSON)

    204 on success

Credit Card Checkout:

  • pnref

    From the payflow response.

  • firstName

    First name on the credit card.

  • lastName

    Last name on the credit card.

  • address

    Address on the credit card.

  • zip

    Zip on the credit card.

Express Checkout:

  • payerId

    The payer ID to pay with.

e-Pay Checkout:

  • paymentInstrumentId

    The ID of the e-pay payment instrument to use.



320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
# File 'app/routes/receipts.rb', line 320

put %r{^/v#{settings.version}/\d+(/families/[^/]+)?/receipts/\d+(\?.*)?$} do
  # update or finalize receipt.
  # post api payment route pass rec id and give them
  # post to info route
  # put receipt updates receipts id put to payment transaction finalizes the receipt
  raise "Receipt is already finalized" unless @receipt.RcptRegStatus == 0
  dirty_cache
  data =
    case request.content_type
    when /json/ then JSON.parse(request.body.read)
    else params
    end
  #logging info
  payment_identifier = ""
  log_hash = {
    :local_time => Time.now,
    :zone_time => Time.zone.now,
    :association_id => @association.id,
  }
  log_hash[:receipt_id] = @receipt.id if @receipt
  settings.notifier.notify!("receipt generation debugging: ",
                            log_hash)

  Receipt.preload(@receipt.id)
  amount = (@receipt.subtotal + @receipt.sales_tax - @receipt.gift_cards).round(2)
  paypal = Paypal.new(@association.pay_pal_configuration)
  ewallet_id = "" #leave here so we can use it in finalize
  if data.has_key?('payerId') && !data['payerId'].empty?
    resp = nil
    until resp
      begin
        resp = paypal.post_with_payer_id(amount, @receipt.credit_card_transaction.PayPalTokenNo, data["payerId"])

        pnref = resp["PNREF"]
        payment_identifier = pnref
        settings.notifier.notify!({:short_message => "Paypal Response",
                                  :full_message => "Paypal Response #{resp}",
                                  :_receipt_id => @receipt.id,
                                    :_association_id => @association.id,
                                    :_association_name => @association.y_part,
                                    :_payment_identifier => payment_identifier})
      rescue Exception => e
        logger.error(e)
      end
    end
    result = resp["RESULT"]
    respmsg = resp["RESPMSG"]
    payer_id = resp["PAYERID"]
    pending_reason = resp["PENDINGREASON"]
    @receipt.store_paypal_transaction(pnref, result, respmsg, payer_id,
                                      pending_reason)
  elsif data.has_key?('pnref') && !data['pnref'].empty?
    payment_identifier = data['pnref']
    resp = nil
    until resp
      begin
        resp = paypal.post_with_pnref(amount, data['pnref'])
        settings.notifier.notify!({:short_message => "Paypal Response",
                                  :full_message => "Paypal Response #{resp}",
                                  :_receipt_id => @receipt.id,
                                    :_association_id => @association.id,
                                    :_association_name => @association.y_part,
                                    :_payment_identifier => payment_identifier})
      rescue Exception => e
        logger.error(e)
      end
    end
    result = resp["ORIGRESULT"]
    respmsg = resp["RESPMSG"]
    response = resp["RESPTEXT"].blank? ? resp["AUTHCODE"] : resp["RESPTEXT"]
    auth_code = resp["AUTHCODE"]
    card_type = get_card_type(resp["CARDTYPE"].to_i)
    card_num = get_card_number(resp["ACCT"])
    name = data.has_key?("firstName") ? data["firstName"] : ''
    name << ' ' if data.has_key?("firstName") && data.has_key?("lastName")
    name << data["lastName"] if data.has_key?("lastName")
    address = data["address"] || ""
    zip = data["zip"] || ""
    expire_date = resp["EXPDATE"]
    ss = @receipt.store_credit_card_transaction(data["pnref"], name, address,
                                           zip, result, response, respmsg,
                                           auth_code, card_type, card_num,
                                                expire_date)
  elsif data.has_key?('paymentInstrumentId') && !data['paymentInstrumentId'].empty?
    instrument = PaymentInstrument.find(data['paymentInstrumentId'])
    until resp
      begin
        resp = paypal.post_with_payment_instrument_id(amount, instrument.EP_CardNumber)
        pnref = resp["PNREF"]
        payment_identifier = pnref
        settings.notifier.notify!({:short_message => "Paypal Response",
                                  :full_message => "Paypal Response #{resp}",
                                  :_receipt_id => @receipt.id,
                                    :_association_id => @association.id,
                                    :_association_name => @association.y_part,
                                    :_payment_identifier => payment_identifier})
      rescue Exception => e
        logger.error(e)
      end
    end
    ewallet_id = instrument.e_wallet.EW_ID
    result = resp["RESULT"]
    respmsg = resp["RESPMSG"]
    auth_code = resp["AUTHCODE"]
    card_type = get_card_type(resp["CARDTYPE"].to_i)
    card_num = get_card_number(resp["ACCT"])
    @receipt.store_credit_card_transaction(pnref,
                                           instrument.EP_CardHolder,
                                           instrument.EP_StreetAddress,
                                           instrument.EP_ZipCode, result,
                                           response,
                                           respmsg,
                                           auth_code,
                                           card_type,
                                           card_num,
                                           instrument.EP_ExpireDate,
                                           instrument.EP_CardNumber)
    instrument.update_attributes(:EP_CardNumber => pnref)
  else
    raise "One of pnref, payerId, or paymentInstrumentId is required to finalize receipt."
  end
  visitor_id = Visitor.where(:CurrentRcptId => @receipt.id).first.id

  begin
    @receipt.finalize(Branch.find(@association.Y_Branch),
                      visitor_id, ewallet_id)

    dirty_cache
    halt 204 #monkey patch halt to send notify log
  rescue Exception => e
    settings.notifier.notify!({:short_message => "Finalizing Receipt Error",
                              :full_message => "Error in Finalizing receipt: #{e.inspect}",
                              :_receipt_id => @receipt.id,
                                :_association_id => @association.id,
                                :_association_name => @association.y_part,
                                :_visitor_id => visitor_id,
                                :_payment_identifier => payment_identifier,
                              :payment_error => e.inspect})
    halt 409
  end
end

- (JSON) put(/<api version>/<associationid>/user_masters/<usermasterid>)

Returns 200 on succesful update

Parameters:

  • password

    if you are changing the password. notice the lower case!

  • firstName

    First Name of person

  • lastName

    Last Name of person

  • lastChange
    • not used really yet
  • active

    is person active

  • branchCode

    The Branch Code the person belongs to

  • accountLocked

    1 or 0 to denote if this account should be locked. probably not used in POST

  • accountLockedTime

    time to lock account

  • email

    Email of person

  • xVoicePassword

    used to set XVoice Password

  • employeeId

    Employee Id

  • dateHired

    The date person was hired

  • employeeType

    options include: "Full Time", "Part Time",

  • payMethod

    options include: "Hourly", "Salary"

Returns:

  • (JSON)

    200 on succesful update



58
59
60
61
62
63
64
65
66
67
68
69
# File 'app/routes/user_masters.rb', line 58

put %r{^/v#{settings.version}/\d+/user_masters/([\w-]+)?$} do |the_id|
  params = request.content_type =~ /json/ ? JSON.parse(request.body.read) : params
  @user_master = UserMaster.find(the_id)
  @user_master.updating_the_password_if_different(params.delete("password"), params.delete("xVoicePassword"))
  data = model_attributes(:user_masters, params)
  if @user_master.update_attributes(data)
    halt 200
  else
    message = @user_master.errors.full_messages.join(". ")
    halt_with_error(400, message)
  end
end

- (Object) send_mail(the_family, email_address)



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'app/routes/emails.rb', line 111

def send_mail(the_family, email_address)
  member =
    if the_family.is_a?(Family)
      the_family.primary_member
    else
      the_family
    end
  unless member.blank?
    base_url = @association.Y_Base_Url
    the_token = member.get_the_password_token
    if the_token.present?

      reset_url = base_url + "/Account/Retrieve?token=" + the_token
      the_mailer = Mailer.new(email_address, @association.y_email, @association.y_name)
      the_mail = the_mailer.reset_password(member.family.FC_LoginID, reset_url)
      the_mailer.delivering(the_mail)
      halt 200, "Email sent"
    else
      halt_with_error(409, "Token was not created properly, please try again")
    end
  else
    halt_record_not_found
  end
end

- (JSON) validate_token

GET route to validate an SSO token

Parameters:

  • client_id

    is the Client ID of the caller requesting access to the SSO system

  • client_secret

    is the Client Secret of the caller requesting access to the SSO system

  • sso_token

    of the user to validate if they're currently signed in to the SSO system

Returns:

  • (JSON)

    with usermaster_id



26
27
28
29
30
31
32
33
34
35
# File 'app/routes/sso.rb', line 26

get %r{^/v#{settings.version}/\d+/sso/validate_token(\?.*)?$} do
  halt_with_error(403, "Not authorized to use the SSO System") unless SsoGate.client_authorized?(params["client_id"], params["client_secret"])
  usermaster_id = SsoGate.find_user_from_token(params["sso_token"])
  halt_with_error(403, "Invalid or expired token") unless usermaster_id

  item = UserMaster.where(:UserId => usermaster_id).first
  tableized_name = item.class.name.tableize
  extra = { :href => url("#{association_base_url(request.url, settings.version)}/#{tableized_name}/#{item[item.class.primary_key]}") }
  render_json({:UserId => usermaster_id}.merge!(extra))
end