diff --git a/app/controllers/paypal_csvs_controller.rb b/app/controllers/paypal_csvs_controller.rb
new file mode 100644
index 0000000..2f48d23
--- /dev/null
+++ b/app/controllers/paypal_csvs_controller.rb
@@ -0,0 +1,28 @@
+class PaypalCsvsController < ApplicationController
+ load_and_authorize_resource :paypal_csv
+ before_filter :authenticate_user!
+
+ def index
+ end
+
+ def show
+ end
+
+ def new
+ end
+
+ def create
+ PaypalCsv.batch_import_from_csv(params[:file].path)
+ redirect_to paypal_csvs_path, :notice => 'Paypal CSV batch was successfully loaded.'
+ end
+
+ def link
+ result = @paypal_csv.link_payment
+ if result.first
+ redirect_to paypal_csvs_url, :notice => 'Payment was successfully linked.'
+ else
+ redirect_to paypal_csvs_url, :notice => result.last
+ end
+ end
+
+end
diff --git a/app/models/ipn.rb b/app/models/ipn.rb
index 2b37017..002a834 100644
--- a/app/models/ipn.rb
+++ b/app/models/ipn.rb
@@ -5,6 +5,14 @@ class Ipn < ActiveRecord::Base
after_create :create_payment
+ def date_parsed
+ begin
+ Date.strptime(self.payment_date, "%H:%M:%S %b %e, %Y %Z")
+ rescue
+ Date.new
+ end
+ end
+
def self.new_from_dynamic_params(params)
ipn = Ipn.new()
diff --git a/app/models/paypal_csv.rb b/app/models/paypal_csv.rb
new file mode 100644
index 0000000..1791aa6
--- /dev/null
+++ b/app/models/paypal_csv.rb
@@ -0,0 +1,73 @@
+require 'csv'
+class PaypalCsv < ActiveRecord::Base
+ attr_accessible :data, :_address_status, :_counterparty_status, :_currency, :_fee, :_from_email_address, :_gross, :_item_id, :_item_title, :_name, :_net, :_status, :_time, :_time_zone, :_to_email_address, :_transaction_id, :_type, :date, :string
+ belongs_to :payment
+
+ after_create :create_payment
+
+ def date_parsed
+ begin
+ Date.strptime(self._date, "%m/%d/%Y")
+ rescue
+ Date.new
+ end
+ end
+
+ def self.batch_import_from_csv(filename)
+ csv = CSV.table(filename)
+ csv.each do |row|
+ paypal_csv = PaypalCsv.new()
+
+ paypal_csv.attributes.each do |c|
+ unless row[c.first.to_sym].nil?
+ paypal_csv[c.first.to_sym] = row[c.first.to_sym]
+ end
+ end
+
+ paypal_csv.data = row.to_json
+ paypal_csv.save
+ end
+
+ return true
+ end
+
+ def link_payment
+ create_payment
+ end
+
+ private
+ def create_payment
+ # find user by email, then by payee
+ user = User.find_by_email(self._from_email_address)
+ user = User.find_by_payee(self._from_email_address) if user.nil? && self._from_email_address.present?
+
+ # Only create payments if the CSV matches a member
+ if user.present?
+ # And is a payment (not a cancellation, etc)
+ payment_types = ["Recurring Payment Received","Payment Received"]
+ if payment_types.include?(self._type)
+ # And a member level
+ if User.member_levels[self._gross.to_i].present?
+ payment = Payment.new
+ payment.date = Date.strptime(self._date, "%m/%d/%Y") #7/6/2013 for Jul 06
+ payment.user_id = user.id
+ payment.amount = self._gross
+ if payment.save
+ self.payment_id = payment.id
+ self.save!
+ else
+ return [false, "Unable to link payment. Payment error: #{payment.errors.full_messages.first}"]
+ end
+ else
+ return [false, "Unable to link payment. Couldn't find membership level '#{self._gross.to_i}'."]
+ end
+ else
+ return [false, "Unable to link payment. Transaction is a '#{self._type}' instead of '#{payment_types.inspect}'."]
+ end
+ else
+ return [false, "Unable to link payment. Couldn't find user/payee '#{self._from_email_address}'."]
+ end
+
+ return [true]
+ end
+end
diff --git a/app/views/ipns/index.html.erb b/app/views/ipns/index.html.erb
index 724c670..70c7709 100644
--- a/app/views/ipns/index.html.erb
+++ b/app/views/ipns/index.html.erb
@@ -6,7 +6,7 @@
Item |
Amount |
- <% @ipns.reverse!.each do |ipn| %>
+ <% @ipns.sort_by(&:date_parsed).reverse!.each do |ipn| %>
<%= ipn.payment_date %> |
<%= ipn.first_name %> <%= ipn.last_name %> |
diff --git a/app/views/paypal_csvs/index.html.erb b/app/views/paypal_csvs/index.html.erb
new file mode 100644
index 0000000..305bf70
--- /dev/null
+++ b/app/views/paypal_csvs/index.html.erb
@@ -0,0 +1,31 @@
+<%= link_to "Upload CSV", new_paypal_csv_path %>
+
+
+ Date |
+ Name |
+ Item |
+ Amount |
+
+<% @paypal_csvs.sort_by(&:date_parsed).reverse!.each do |paypal_csv| %>
+
+ <%= paypal_csv.date %> |
+ <%= paypal_csv._name %> |
+ <%= paypal_csv._item_title %> |
+
+ <% if paypal_csv._gross.blank? %>
+ <%= paypal_csv._type %>
+ <% else %>
+ <%= paypal_csv._gross %>
+ <% end %>
+ |
+
+ <% if paypal_csv.payment.present? %>
+ <%= link_to "Linked Payment", paypal_csv.payment %>
+ <% else %>
+ <%= link_to "Try to link email '#{paypal_csv._from_email_address}' at membership level '#{paypal_csv._gross.to_i}'", link_paypal_csv_path(paypal_csv) %>
+ <% end %>
+ |
+ <%= link_to "Details", paypal_csv %> |
+
+<% end %>
+
diff --git a/app/views/paypal_csvs/new.html.erb b/app/views/paypal_csvs/new.html.erb
new file mode 100644
index 0000000..275f41e
--- /dev/null
+++ b/app/views/paypal_csvs/new.html.erb
@@ -0,0 +1,15 @@
+
+
+<%= form_tag('/paypal_csvs', :multipart => true) do |f| %>
+
+ <%= label_tag :file %>
+ <%= file_field_tag :file %>
+
+
+ <%= submit_tag %>
+
+<% end %>
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index 4cfeb05..ba34d4d 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -4,6 +4,9 @@ Dooraccess::Application.routes.draw do
match 'ipns/:id/link' => 'ipns#link', :as => :link_ipn
match 'ipns/:id/validate' => 'ipns#validate', :as => :validate_ipn
+ resources :paypal_csvs
+ match 'paypal_csvs/:id/link' => 'paypal_csvs#link', :as => :link_paypal_csv
+
resources :payments
resources :user_certifications
diff --git a/db/migrate/20130828104240_create_paypal_csvs.rb b/db/migrate/20130828104240_create_paypal_csvs.rb
new file mode 100644
index 0000000..f0d682e
--- /dev/null
+++ b/db/migrate/20130828104240_create_paypal_csvs.rb
@@ -0,0 +1,28 @@
+class CreatePaypalCsvs < ActiveRecord::Migration
+ def change
+ create_table :paypal_csvs do |t|
+ t.integer :payment_id
+ t.text :data
+ t.string :date
+ t.string :_time
+ t.string :_time_zone
+ t.string :_name
+ t.string :_type
+ t.string :_status
+ t.string :_currency
+ t.string :_gross
+ t.string :_fee
+ t.string :_net
+ t.string :_from_email_address
+ t.string :_to_email_address
+ t.string :_transaction_id
+ t.string :_counterparty_status
+ t.string :_address_status
+ t.string :_item_title
+ t.string :_item_id
+ t.string :string
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index ac3f771..25dbad2 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -1,3 +1,4 @@
+# encoding: UTF-8
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
@@ -10,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20130824072157) do
+ActiveRecord::Schema.define(:version => 20130828104240) do
create_table "cards", :force => true do |t|
t.string "card_number"
@@ -90,6 +91,31 @@ ActiveRecord::Schema.define(:version => 20130824072157) do
add_index "payments", ["user_id"], :name => "index_payments_on_user_id"
+ create_table "paypal_csvs", :force => true do |t|
+ t.integer "payment_id"
+ t.text "data"
+ t.string "date"
+ t.string "_time"
+ t.string "_time_zone"
+ t.string "_name"
+ t.string "_type"
+ t.string "_status"
+ t.string "_currency"
+ t.string "_gross"
+ t.string "_fee"
+ t.string "_net"
+ t.string "_from_email_address"
+ t.string "_to_email_address"
+ t.string "_transaction_id"
+ t.string "_counterparty_status"
+ t.string "_address_status"
+ t.string "_item_title"
+ t.string "_item_id"
+ t.string "string"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
create_table "user_certifications", :force => true do |t|
t.integer "user_id"
t.integer "certification_id"
diff --git a/test/fixtures/paypal_csvs.yml b/test/fixtures/paypal_csvs.yml
new file mode 100644
index 0000000..c103612
--- /dev/null
+++ b/test/fixtures/paypal_csvs.yml
@@ -0,0 +1,41 @@
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html
+
+one:
+ date: MyString
+ _time: MyString
+ _time_zone: MyString
+ _name: MyString
+ _type: MyString
+ _status: MyString
+ _currency: MyString
+ _gross: MyString
+ _fee: MyString
+ _net: MyString
+ _from_email_address: MyString
+ _to_email_address: MyString
+ _transaction_id: MyString
+ _counterparty_status: MyString
+ _address_status: MyString
+ _item_title: MyString
+ _item_id: MyString
+ string: MyString
+
+two:
+ date: MyString
+ _time: MyString
+ _time_zone: MyString
+ _name: MyString
+ _type: MyString
+ _status: MyString
+ _currency: MyString
+ _gross: MyString
+ _fee: MyString
+ _net: MyString
+ _from_email_address: MyString
+ _to_email_address: MyString
+ _transaction_id: MyString
+ _counterparty_status: MyString
+ _address_status: MyString
+ _item_title: MyString
+ _item_id: MyString
+ string: MyString
diff --git a/test/unit/paypal_csv_test.rb b/test/unit/paypal_csv_test.rb
new file mode 100644
index 0000000..c610e02
--- /dev/null
+++ b/test/unit/paypal_csv_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class PaypalCsvTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end