* VRFS-3080 - partial refund manual process done
This commit is contained in:
parent
989518fa68
commit
4cce21e7f8
|
|
@ -1,20 +1,29 @@
|
||||||
require 'jam_ruby/recurly_client'
|
require 'jam_ruby/recurly_client'
|
||||||
ActiveAdmin.register JamRuby::JamTrackRight, :as => 'JamTrackRights' do
|
ActiveAdmin.register JamRuby::JamTrackRight, :as => 'JamTrackRights' do
|
||||||
|
|
||||||
menu :label => 'Purchased JamTracks', :parent => 'JamTracks'
|
menu :label => 'Purchased JamTracks', :parent => 'Purchases'
|
||||||
|
|
||||||
config.sort_order = 'updated_at DESC'
|
config.sort_order = 'created_at DESC'
|
||||||
config.batch_actions = false
|
config.batch_actions = false
|
||||||
|
|
||||||
#form :partial => 'form'
|
#form :partial => 'form'
|
||||||
|
|
||||||
|
filter :user_id
|
||||||
|
|
||||||
|
filter :user_id,
|
||||||
|
:label => "USER ID", :required => false,
|
||||||
|
:wrapper_html => { :style => "list-style: none" }
|
||||||
|
|
||||||
|
|
||||||
|
filter :jam_track
|
||||||
|
|
||||||
index do
|
index do
|
||||||
default_actions
|
default_actions
|
||||||
|
|
||||||
column "Order" do |right|
|
#column "Order" do |right|
|
||||||
link_to("Place", order_admin_jam_track_right_path(right)) + " | " +
|
#link_to("Place", order_admin_jam_track_right_path(right)) + " | " +
|
||||||
link_to("Refund", refund_admin_jam_track_right_path(right))
|
# link_to("Refund", refund_admin_jam_track_right_path(right))
|
||||||
end
|
#end
|
||||||
|
|
||||||
column "Last Name" do |right|
|
column "Last Name" do |right|
|
||||||
right.user.last_name
|
right.user.last_name
|
||||||
|
|
@ -23,13 +32,15 @@ ActiveAdmin.register JamRuby::JamTrackRight, :as => 'JamTrackRights' do
|
||||||
right.user.first_name
|
right.user.first_name
|
||||||
end
|
end
|
||||||
column "Jam Track" do |right|
|
column "Jam Track" do |right|
|
||||||
link_to(right.jam_track.name, admin_jam_track_right_path(right.jam_track))
|
link_to(right.jam_track.name, admin_jam_track_path(right.jam_track))
|
||||||
# right.jam_track
|
# right.jam_track
|
||||||
end
|
end
|
||||||
column "Plan Code" do |right|
|
column "Plan Code" do |right|
|
||||||
|
|
||||||
right.jam_track.plan_code
|
right.jam_track.plan_code
|
||||||
end
|
end
|
||||||
|
column "Redeemed" do |right|
|
||||||
|
right.redeemed ? 'Y' : 'N'
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
@ -42,6 +53,9 @@ ActiveAdmin.register JamRuby::JamTrackRight, :as => 'JamTrackRights' do
|
||||||
f.actions
|
f.actions
|
||||||
end
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
|
||||||
member_action :order, :method => :get do
|
member_action :order, :method => :get do
|
||||||
right = JamTrackRight.where("id=?",params[:id]).first
|
right = JamTrackRight.where("id=?",params[:id]).first
|
||||||
user = right.user
|
user = right.user
|
||||||
|
|
@ -84,4 +98,5 @@ ActiveAdmin.register JamRuby::JamTrackRight, :as => 'JamTrackRights' do
|
||||||
redirect_to admin_jam_track_rights_path, notice: "Issued full refund on #{right.jam_track} for #{right.user.to_s}"
|
redirect_to admin_jam_track_rights_path, notice: "Issued full refund on #{right.jam_track} for #{right.user.to_s}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
=end
|
||||||
end
|
end
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
ActiveAdmin.register JamRuby::RecurlyTransactionWebHook, :as => 'RecurlyHooks' do
|
||||||
|
|
||||||
|
menu :label => 'Recurly Transaction Hooks', :parent => 'Purchases'
|
||||||
|
|
||||||
|
config.sort_order = 'created_at DESC'
|
||||||
|
config.batch_actions = false
|
||||||
|
|
||||||
|
actions :all, :except => [:destroy]
|
||||||
|
|
||||||
|
#form :partial => 'form'
|
||||||
|
|
||||||
|
|
||||||
|
filter :transaction_type, :as => :select, :collection => JamRuby::RecurlyTransactionWebHook::HOOK_TYPES
|
||||||
|
filter :user_id,
|
||||||
|
:label => "USER ID", :required => false,
|
||||||
|
:wrapper_html => { :style => "list-style: none" }
|
||||||
|
|
||||||
|
filter :invoice_id
|
||||||
|
|
||||||
|
form :partial => 'form'
|
||||||
|
|
||||||
|
index do
|
||||||
|
|
||||||
|
default_actions
|
||||||
|
|
||||||
|
column :transaction_type
|
||||||
|
column :transaction_at
|
||||||
|
column :amount_in_cents
|
||||||
|
column 'Transaction' do |hook| link_to('Go to Recurly', Rails.application.config.recurly_root_url + "/transactions/#{hook.recurly_transaction_id}") end
|
||||||
|
column 'Invoice' do |hook| link_to(hook.invoice_number, Rails.application.config.recurly_root_url + "/invoices/#{hook.invoice_number}") end
|
||||||
|
column :admin_description
|
||||||
|
column 'User' do |hook| link_to("#{hook.user.email} (#{hook.user.name})", admin_user_path(hook.user.id)) end
|
||||||
|
|
||||||
|
#column "Order" do |right|
|
||||||
|
#link_to("Place", order_admin_jam_track_right_path(right)) + " | " +
|
||||||
|
# link_to("Refund", refund_admin_jam_track_right_path(right))
|
||||||
|
#end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
= semantic_form_for([:admin, resource], :html => {:multipart => true}, :url => resource.new_record? ? admin_recurly_transaction_web_hooks_path : "#{ENV['RAILS_RELATIVE_URL_ROOT']}/admin/recurly_hooks/#{resource.id}") do |f|
|
||||||
|
= f.semantic_errors *f.object.errors.keys
|
||||||
|
= f.inputs name: 'Recurly Web Hook fields' do
|
||||||
|
= f.input :admin_description, :input_html => { :rows=>1, :maxlength=>200, }, hint: "this will display on the user's payment history page"
|
||||||
|
= f.input :jam_track, collection: JamRuby::JamTrack.all, include_blank: true, hint: "Please indicate which JamTrack this refund for, if not set"
|
||||||
|
= f.actions
|
||||||
|
|
@ -83,6 +83,7 @@ module JamAdmin
|
||||||
config.external_port = ENV['EXTERNAL_PORT'] || 3000
|
config.external_port = ENV['EXTERNAL_PORT'] || 3000
|
||||||
config.external_protocol = ENV['EXTERNAL_PROTOCOL'] || 'http://'
|
config.external_protocol = ENV['EXTERNAL_PROTOCOL'] || 'http://'
|
||||||
config.external_root_url = "#{config.external_protocol}#{config.external_hostname}#{(config.external_port == 80 || config.external_port == 443) ? '' : ':' + config.external_port.to_s}"
|
config.external_root_url = "#{config.external_protocol}#{config.external_hostname}#{(config.external_port == 80 || config.external_port == 443) ? '' : ':' + config.external_port.to_s}"
|
||||||
|
config.recurly_root_url = 'https://jamkazam-development.recurly.com'
|
||||||
|
|
||||||
# where is rabbitmq?
|
# where is rabbitmq?
|
||||||
config.rabbitmq_host = "localhost"
|
config.rabbitmq_host = "localhost"
|
||||||
|
|
|
||||||
|
|
@ -279,3 +279,4 @@ recurly_adjustments.sql
|
||||||
signup_hints.sql
|
signup_hints.sql
|
||||||
packaging_notices.sql
|
packaging_notices.sql
|
||||||
first_played_jamtrack_at.sql
|
first_played_jamtrack_at.sql
|
||||||
|
payment_history.sql
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
ALTER TABLE recurly_transaction_web_hooks ADD COLUMN admin_description VARCHAR;
|
||||||
|
ALTER TABLE recurly_transaction_web_hooks ADD COLUMN jam_track_id VARCHAR(64) REFERENCES jam_tracks(id);
|
||||||
|
|
||||||
|
CREATE VIEW payment_histories AS
|
||||||
|
SELECT id AS sale_id,
|
||||||
|
CAST(NULL as VARCHAR) AS recurly_transaction_web_hook_id,
|
||||||
|
user_id,
|
||||||
|
created_at,
|
||||||
|
'sale' AS transaction_type
|
||||||
|
FROM sales s
|
||||||
|
UNION ALL
|
||||||
|
SELECT CAST(NULL as VARCHAR) AS sale_id,
|
||||||
|
id AS recurly_transaction_web_hook_id,
|
||||||
|
user_id,
|
||||||
|
transaction_at AS created_at,
|
||||||
|
transaction_type
|
||||||
|
FROM recurly_transaction_web_hooks;
|
||||||
|
|
@ -207,6 +207,7 @@ require "jam_ruby/models/generic_state"
|
||||||
require "jam_ruby/models/score_history"
|
require "jam_ruby/models/score_history"
|
||||||
require "jam_ruby/models/jam_company"
|
require "jam_ruby/models/jam_company"
|
||||||
require "jam_ruby/models/user_sync"
|
require "jam_ruby/models/user_sync"
|
||||||
|
require "jam_ruby/models/payment_history"
|
||||||
require "jam_ruby/models/video_source"
|
require "jam_ruby/models/video_source"
|
||||||
require "jam_ruby/models/text_message"
|
require "jam_ruby/models/text_message"
|
||||||
require "jam_ruby/models/sale"
|
require "jam_ruby/models/sale"
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,16 @@ module JamRuby
|
||||||
subject: options[:subject])
|
subject: options[:subject])
|
||||||
end
|
end
|
||||||
|
|
||||||
def recurly_alerts(options)
|
def recurly_alerts(user, options)
|
||||||
|
|
||||||
|
body = options[:body]
|
||||||
|
body << "\n\n"
|
||||||
|
body << "User " << user.admin_url + "\n"
|
||||||
|
body << "User's JamTracks " << user.jam_track_rights_admin_url + "\n"
|
||||||
|
|
||||||
mail(to: APP_CONFIG.email_recurly_notice,
|
mail(to: APP_CONFIG.email_recurly_notice,
|
||||||
from: APP_CONFIG.email_generic_from,
|
from: APP_CONFIG.email_generic_from,
|
||||||
body: options[:body],
|
body: body,
|
||||||
content_type: "text/plain",
|
content_type: "text/plain",
|
||||||
subject: options[:subject])
|
subject: options[:subject])
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,10 @@ module JamRuby
|
||||||
# has_many :plays, :class_name => "JamRuby::PlayablePlay", :foreign_key => :jam_track_id, :dependent => :destroy
|
# has_many :plays, :class_name => "JamRuby::PlayablePlay", :foreign_key => :jam_track_id, :dependent => :destroy
|
||||||
# VRFS-2916 jam_tracks.id is varchar: ADD
|
# VRFS-2916 jam_tracks.id is varchar: ADD
|
||||||
has_many :plays, :class_name => "JamRuby::PlayablePlay", :as => :playable, :dependent => :destroy
|
has_many :plays, :class_name => "JamRuby::PlayablePlay", :as => :playable, :dependent => :destroy
|
||||||
|
|
||||||
|
# when we know what JamTrack this refund is related to, these are associated
|
||||||
|
belongs_to :recurly_transactions, class_name: 'JamRuby::RecurlyTransactionWebHook'
|
||||||
|
|
||||||
accepts_nested_attributes_for :jam_track_tracks, allow_destroy: true
|
accepts_nested_attributes_for :jam_track_tracks, allow_destroy: true
|
||||||
accepts_nested_attributes_for :jam_track_tap_ins, allow_destroy: true
|
accepts_nested_attributes_for :jam_track_tap_ins, allow_destroy: true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
module JamRuby
|
||||||
|
class PaymentHistory < ActiveRecord::Base
|
||||||
|
|
||||||
|
self.table_name = 'payment_histories'
|
||||||
|
|
||||||
|
belongs_to :sale
|
||||||
|
belongs_to :recurly_transaction_web_hook
|
||||||
|
|
||||||
|
|
||||||
|
def self.index(user, params = {})
|
||||||
|
|
||||||
|
limit = params[:per_page]
|
||||||
|
limit ||= 20
|
||||||
|
limit = limit.to_i
|
||||||
|
|
||||||
|
query = PaymentHistory.limit(limit)
|
||||||
|
.includes(sale: [:sale_line_items], recurly_transaction_web_hook:[])
|
||||||
|
.where(user_id: user.id)
|
||||||
|
.where("transaction_type = 'sale' OR transaction_type = 'refund' OR transaction_type = 'void'")
|
||||||
|
.order('created_at DESC')
|
||||||
|
|
||||||
|
|
||||||
|
current_page = params[:page].nil? ? 1 : params[:page].to_i
|
||||||
|
next_page = current_page + 1
|
||||||
|
|
||||||
|
# will_paginate gem
|
||||||
|
query = query.paginate(:page => current_page, :per_page => limit)
|
||||||
|
|
||||||
|
if query.length == 0 # no more results
|
||||||
|
{ query: query, next_page: nil}
|
||||||
|
elsif query.length < limit # no more results
|
||||||
|
{ query: query, next_page: nil}
|
||||||
|
else
|
||||||
|
{ query: query, next_page: next_page }
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
module JamRuby
|
module JamRuby
|
||||||
class RecurlyTransactionWebHook < ActiveRecord::Base
|
class RecurlyTransactionWebHook < ActiveRecord::Base
|
||||||
|
|
||||||
|
attr_accessible :admin_description, :jam_track_id, as: :admin
|
||||||
|
|
||||||
belongs_to :user, class_name: 'JamRuby::User'
|
belongs_to :user, class_name: 'JamRuby::User'
|
||||||
belongs_to :sale_line_item, class_name: 'JamRuby::SaleLineItem', foreign_key: 'subscription_id', primary_key: 'recurly_subscription_uuid', inverse_of: :recurly_transactions
|
belongs_to :sale_line_item, class_name: 'JamRuby::SaleLineItem', foreign_key: 'subscription_id', primary_key: 'recurly_subscription_uuid', inverse_of: :recurly_transactions
|
||||||
belongs_to :sale, class_name: 'JamRuby::Sale', foreign_key: 'invoice_id', primary_key: 'recurly_invoice_id', inverse_of: :recurly_transactions
|
belongs_to :sale, class_name: 'JamRuby::Sale', foreign_key: 'invoice_id', primary_key: 'recurly_invoice_id', inverse_of: :recurly_transactions
|
||||||
|
|
||||||
|
# when we know what JamTrack this refund is related to, we set this value
|
||||||
|
belongs_to :jam_track, class_name: 'JamRuby::JamTrack'
|
||||||
|
|
||||||
validates :recurly_transaction_id, presence: true
|
validates :recurly_transaction_id, presence: true
|
||||||
validates :action, presence: true
|
validates :action, presence: true
|
||||||
validates :status, presence: true
|
validates :status, presence: true
|
||||||
|
|
@ -17,6 +22,9 @@ module JamRuby
|
||||||
REFUND = 'refund'
|
REFUND = 'refund'
|
||||||
VOID = 'void'
|
VOID = 'void'
|
||||||
|
|
||||||
|
|
||||||
|
HOOK_TYPES = [SUCCESSFUL_PAYMENT, FAILED_PAYMENT, REFUND, VOID]
|
||||||
|
|
||||||
def is_credit_type?
|
def is_credit_type?
|
||||||
transaction_type == REFUND || transaction_type == VOID
|
transaction_type == REFUND || transaction_type == VOID
|
||||||
end
|
end
|
||||||
|
|
@ -46,6 +54,10 @@ module JamRuby
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def admin_url
|
||||||
|
APP_CONFIG.admin_root_url + "/admin/recurly_hooks/" + id
|
||||||
|
end
|
||||||
|
|
||||||
# see spec for examples of XML
|
# see spec for examples of XML
|
||||||
def self.create_from_xml(document)
|
def self.create_from_xml(document)
|
||||||
|
|
||||||
|
|
@ -81,6 +93,7 @@ module JamRuby
|
||||||
|
|
||||||
# now that we have the transaction saved, we also need to delete the jam_track_right if this is a refund, or voided
|
# now that we have the transaction saved, we also need to delete the jam_track_right if this is a refund, or voided
|
||||||
|
|
||||||
|
|
||||||
if transaction.transaction_type == 'refund' || transaction.transaction_type == 'void'
|
if transaction.transaction_type == 'refund' || transaction.transaction_type == 'void'
|
||||||
sale = Sale.find_by_recurly_invoice_id(transaction.invoice_id)
|
sale = Sale.find_by_recurly_invoice_id(transaction.invoice_id)
|
||||||
|
|
||||||
|
|
@ -91,33 +104,44 @@ module JamRuby
|
||||||
jam_track_right = jam_track.right_for_user(transaction.user) if jam_track
|
jam_track_right = jam_track.right_for_user(transaction.user) if jam_track
|
||||||
if jam_track_right
|
if jam_track_right
|
||||||
jam_track_right.destroy
|
jam_track_right.destroy
|
||||||
AdminMailer.recurly_alerts({
|
|
||||||
subject:"NOTICE: #{transaction.user.email} has had JamTrack: #{jam_track.name} revoked",
|
# associate which JamTrack we assume this is related to in this one success case
|
||||||
body: "A void event came from Recurly for sale with Recurly invoice ID #{sale.recurly_invoice_id}. We deleted their right to the track in our own database as a result."
|
transaction.jam_track = jam_track
|
||||||
}).deliver
|
transaction.save!
|
||||||
|
|
||||||
|
AdminMailer.recurly_alerts(transaction.user, {
|
||||||
|
subject: "NOTICE: #{transaction.user.email} has had JamTrack: #{jam_track.name} revoked",
|
||||||
|
body: "A #{transaction.transaction_type} event came from Recurly for sale with Recurly invoice ID #{sale.recurly_invoice_id}. We deleted their right to the track in our own database as a result."
|
||||||
|
}).deliver
|
||||||
else
|
else
|
||||||
AdminMailer.recurly_alerts({
|
AdminMailer.recurly_alerts(transaction.user, {
|
||||||
subject:"NOTICE: #{transaction.user.email} got a refund, but unable to find JamTrackRight to delete",
|
subject: "NOTICE: #{transaction.user.email} got a refund, but unable to find JamTrackRight to delete",
|
||||||
body: "This should just mean the user already has no rights to the JamTrackRight when the refund came in. Not a big deal, but sort of weird..."
|
body: "This should just mean the user already has no rights to the JamTrackRight when the refund came in. Not a big deal, but sort of weird..."
|
||||||
}).deliver
|
}).deliver
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
AdminMailer.recurly_alerts({
|
AdminMailer.recurly_alerts(transaction.user, {
|
||||||
subject:"ACTION REQUIRED: #{transaction.user.email} got a refund it was not for total value of a JamTrack sale",
|
subject: "ACTION REQUIRED: #{transaction.user.email} got a refund it was not for total value of a JamTrack sale",
|
||||||
body: "We received a refund notice for an amount that was not the same as the original sale. So, no action was taken in the database. sale total: #{sale.recurly_total_in_cents}, refund amount: #{transaction.amount_in_cents}"
|
body: "We received a #{transaction.transaction_type} notice for an amount that was not the same as the original sale. So, no action was taken in the database. sale total: #{sale.recurly_total_in_cents}, refund amount: #{transaction.amount_in_cents}"
|
||||||
}).deliver
|
}).deliver
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
else
|
else
|
||||||
AdminMailer.recurly_alerts({
|
AdminMailer.recurly_alerts(transaction.user, {
|
||||||
subject: "ACTION REQUIRED: #{transaction.user.email} has refund on invoice with multiple JamTracks",
|
subject: "ACTION REQUIRED: #{transaction.user.email} has refund on invoice with multiple JamTracks",
|
||||||
body: "You will have to manually revoke any JamTrackRights in our database for the appropriate JamTracks"
|
body: "You will have to manually revoke any JamTrackRights in our database for the appropriate JamTracks"
|
||||||
}).deliver
|
}).deliver
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
AdminMailer.recurly_alerts(transaction.user, {
|
||||||
|
subject: "ACTION REQUIRED: #{transaction.user.email} has refund with no correlator to sales",
|
||||||
|
body: "You will have to manually revoke any JamTrackRights in our database for the appropriate JamTracks"
|
||||||
|
}).deliver
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
transaction
|
transaction
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1573,6 +1573,10 @@ module JamRuby
|
||||||
APP_CONFIG.admin_root_url + "/admin/users/" + id
|
APP_CONFIG.admin_root_url + "/admin/users/" + id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def jam_track_rights_admin_url
|
||||||
|
APP_CONFIG.admin_root_url + "/admin/jam_track_rights?q[user_id_equals]=#{id}&commit=Filter&order=created_at DESC"
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def create_remember_token
|
def create_remember_token
|
||||||
self.remember_token = SecureRandom.urlsafe_base64
|
self.remember_token = SecureRandom.urlsafe_base64
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe PaymentHistory do
|
||||||
|
|
||||||
|
let(:user) {FactoryGirl.create(:user)}
|
||||||
|
let(:user2) {FactoryGirl.create(:user)}
|
||||||
|
let(:jam_track) {FactoryGirl.create(:jam_track)}
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "index" do
|
||||||
|
it "empty" do
|
||||||
|
result = PaymentHistory.index(user)
|
||||||
|
result[:query].length.should eq(0)
|
||||||
|
result[:next].should eq(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "one" do
|
||||||
|
sale = Sale.create_jam_track_sale(user)
|
||||||
|
shopping_cart = ShoppingCart.create(user, jam_track)
|
||||||
|
sale_line_item = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, 'some_adjustment_uuid', nil)
|
||||||
|
|
||||||
|
result = PaymentHistory.index(user)
|
||||||
|
result[:query].length.should eq(1)
|
||||||
|
result[:next].should eq(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "user filtered correctly" do
|
||||||
|
sale = Sale.create_jam_track_sale(user)
|
||||||
|
shopping_cart = ShoppingCart.create(user, jam_track)
|
||||||
|
sale_line_item = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, 'some_adjustment_uuid', nil)
|
||||||
|
|
||||||
|
result = PaymentHistory.index(user)
|
||||||
|
result[:query].length.should eq(1)
|
||||||
|
result[:next].should eq(nil)
|
||||||
|
|
||||||
|
sale2 = Sale.create_jam_track_sale(user2)
|
||||||
|
shopping_cart = ShoppingCart.create(user2, jam_track)
|
||||||
|
sale_line_item2 = SaleLineItem.create_from_shopping_cart(sale2, shopping_cart, nil, 'some_adjustment_uuid', nil)
|
||||||
|
|
||||||
|
result = PaymentHistory.index(user)
|
||||||
|
result[:query].length.should eq(1)
|
||||||
|
result[:next].should eq(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -51,41 +51,33 @@ context.JK.AccountPaymentHistoryScreen = class AccountPaymentHistoryScreen
|
||||||
|
|
||||||
renderPayments:(response) =>
|
renderPayments:(response) =>
|
||||||
if response.entries? && response.entries.length > 0
|
if response.entries? && response.entries.length > 0
|
||||||
for sale in response.entries
|
for paymentHistory in response.entries
|
||||||
amt = sale.recurly_total_in_cents
|
if paymentHistory.sale?
|
||||||
amt = 0 if !amt?
|
# this is a sale
|
||||||
|
sale = paymentHistory.sale
|
||||||
original_total = sale.state.original_total
|
amt = sale.recurly_total_in_cents
|
||||||
refund_total = sale.state.refund_total
|
status = 'paid'
|
||||||
|
displayAmount = ' $' + (amt/100).toFixed(2)
|
||||||
refund_state = null
|
date = context.JK.formatDate(sale.created_at, true)
|
||||||
if original_total != 0 # the enclosed logic does not work for free purchases
|
items = []
|
||||||
if refund_total == original_total
|
for line_item in sale.line_items
|
||||||
refund_state = 'refunded'
|
items.push(line_item.product_info?.name)
|
||||||
else if refund_total != 0 and refund_total < original_total
|
description = items.join(', ')
|
||||||
refund_state = 'partial refund'
|
else
|
||||||
|
# this is a recurly webhook
|
||||||
|
transaction = paymentHistory.transaction
|
||||||
displayAmount = (amt/100).toFixed(2)
|
amt = transaction.amount_in_cents
|
||||||
status = 'paid'
|
status = transaction.transaction_type
|
||||||
|
displayAmount = '($' + (amt/100).toFixed(2) + ')'
|
||||||
if sale.state.voided
|
date = context.JK.formatDate(transaction.transaction_at, true)
|
||||||
status = 'voided'
|
description = transaction.admin_description
|
||||||
displayAmount = (amt/100).toFixed(2)
|
|
||||||
else if refund_state?
|
|
||||||
status = refund_state
|
|
||||||
displayAmount = (amt/100).toFixed(2) + " (refunded: #{(refund_total/100).toFixed(2)})"
|
|
||||||
|
|
||||||
description = []
|
|
||||||
for line_item in sale.line_items
|
|
||||||
description.push(line_item.product_info?.name)
|
|
||||||
|
|
||||||
payment = {
|
payment = {
|
||||||
date: context.JK.formatDate(sale.created_at, true)
|
date: date
|
||||||
amount: displayAmount
|
amount: displayAmount
|
||||||
status: status
|
status: status
|
||||||
payment_method: 'Credit Card',
|
payment_method: 'Credit Card'
|
||||||
description: description.join(', ')
|
description: description
|
||||||
}
|
}
|
||||||
|
|
||||||
tr = $(context._.template(@rowTemplate, payment, { variable: 'data' }));
|
tr = $(context._.template(@rowTemplate, payment, { variable: 'data' }));
|
||||||
|
|
@ -98,9 +90,9 @@ context.JK.AccountPaymentHistoryScreen = class AccountPaymentHistoryScreen
|
||||||
|
|
||||||
# Turn in to HTML rows and append:
|
# Turn in to HTML rows and append:
|
||||||
#@tbody.html("")
|
#@tbody.html("")
|
||||||
@next = response.next_page
|
@next = response.next
|
||||||
@renderPayments(response)
|
@renderPayments(response)
|
||||||
if response.next_page == null
|
if response.next == null
|
||||||
# if we less results than asked for, end searching
|
# if we less results than asked for, end searching
|
||||||
@scroller.infinitescroll 'pause'
|
@scroller.infinitescroll 'pause'
|
||||||
@logger.debug("end of history")
|
@logger.debug("end of history")
|
||||||
|
|
@ -146,7 +138,7 @@ context.JK.AccountPaymentHistoryScreen = class AccountPaymentHistoryScreen
|
||||||
msg: $('<div class="infinite-scroll-loader">Loading ...</div>')
|
msg: $('<div class="infinite-scroll-loader">Loading ...</div>')
|
||||||
img: '/assets/shared/spinner.gif'
|
img: '/assets/shared/spinner.gif'
|
||||||
path: (page) =>
|
path: (page) =>
|
||||||
'/api/sales?' + $.param(that.buildQuery())
|
'/api/payment_histories?' + $.param(that.buildQuery())
|
||||||
|
|
||||||
}, (json, opts) =>
|
}, (json, opts) =>
|
||||||
this.salesHistoryDone(json)
|
this.salesHistoryDone(json)
|
||||||
|
|
|
||||||
|
|
@ -1508,7 +1508,7 @@
|
||||||
function getSalesHistory(options) {
|
function getSalesHistory(options) {
|
||||||
return $.ajax({
|
return $.ajax({
|
||||||
type: "GET",
|
type: "GET",
|
||||||
url: '/api/sales?' + $.param(options),
|
url: '/api/payment_histories?' + $.param(options),
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
contentType: 'application/json'
|
contentType: 'application/json'
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.voided {
|
&.voided {
|
||||||
|
|
||||||
text-decoration:line-through;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
class ApiPaymentHistoriesController < ApiController
|
||||||
|
|
||||||
|
before_filter :api_signed_in_user
|
||||||
|
|
||||||
|
respond_to :json
|
||||||
|
|
||||||
|
def index
|
||||||
|
data = PaymentHistory.index(current_user,
|
||||||
|
page: params[:page],
|
||||||
|
per_page: params[:per_page])
|
||||||
|
|
||||||
|
|
||||||
|
@payment_histories = data[:query]
|
||||||
|
|
||||||
|
@next = data[:next_page]
|
||||||
|
render "api_payment_histories/index", :layout => nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -4,6 +4,7 @@ class ApiSalesController < ApiController
|
||||||
|
|
||||||
respond_to :json
|
respond_to :json
|
||||||
|
|
||||||
|
# deprecated in favor of ApiPaymentHistoriesController
|
||||||
def index
|
def index
|
||||||
data = Sale.index(current_user,
|
data = Sale.index(current_user,
|
||||||
page: params[:page],
|
page: params[:page],
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
node :next do |page|
|
||||||
|
@next
|
||||||
|
end
|
||||||
|
|
||||||
|
node :entries do |page|
|
||||||
|
partial "api_payment_histories/show", object: @payment_histories
|
||||||
|
end
|
||||||
|
|
||||||
|
node :total_entries do |page|
|
||||||
|
@payment_histories.total_entries
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
object @payment_history
|
||||||
|
|
||||||
|
child :sale do
|
||||||
|
attributes :id, :recurly_invoice_id, :recurly_subtotal_in_cents, :recurly_tax_in_cents, :recurly_total_in_cents, :recurly_currency, :sale_type, :recurly_invoice_number, :state, :created_at
|
||||||
|
|
||||||
|
child(:sale_line_items => :line_items) {
|
||||||
|
attributes :id, :product_info
|
||||||
|
}
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
child(:recurly_transaction_web_hook => :transaction) do
|
||||||
|
attributes :id, :transaction_type, :subscription_id, :amount_in_cents, :invoice_id, :admin_description, :message, :transaction_at, :admin_description
|
||||||
|
end
|
||||||
|
|
@ -41,4 +41,4 @@ script#template-payment-history-row type="text/template"
|
||||||
td.capitalize
|
td.capitalize
|
||||||
| {{data.status}}
|
| {{data.status}}
|
||||||
td.amount class="{{data.status}}"
|
td.amount class="{{data.status}}"
|
||||||
| ${{data.amount}}
|
| {{data.amount}}
|
||||||
|
|
|
||||||
|
|
@ -280,7 +280,7 @@ SampleApp::Application.routes.draw do
|
||||||
match '/recurly/place_order' => 'api_recurly#place_order', :via => :post
|
match '/recurly/place_order' => 'api_recurly#place_order', :via => :post
|
||||||
|
|
||||||
# sale info
|
# sale info
|
||||||
match '/sales' => 'api_sales#index', :via => :get
|
match '/payment_histories' => 'api_payment_histories#index', :via => :get
|
||||||
|
|
||||||
# login/logout
|
# login/logout
|
||||||
match '/auth_session' => 'api_users#auth_session_create', :via => :post
|
match '/auth_session' => 'api_users#auth_session_create', :via => :post
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
describe ApiSalesController do
|
describe ApiPaymentHistoriesController do
|
||||||
render_views
|
render_views
|
||||||
|
|
||||||
let(:user) {FactoryGirl.create(:user)}
|
let(:user) {FactoryGirl.create(:user)}
|
||||||
|
|
@ -19,6 +19,7 @@ describe ApiSalesController do
|
||||||
body = JSON.parse(response.body)
|
body = JSON.parse(response.body)
|
||||||
body['next_page'].should be_nil
|
body['next_page'].should be_nil
|
||||||
body['entries'].should eq([])
|
body['entries'].should eq([])
|
||||||
|
body['total_entries'].should eq(0)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "one item" do
|
it "one item" do
|
||||||
|
|
@ -36,21 +37,28 @@ describe ApiSalesController do
|
||||||
entries = body['entries']
|
entries = body['entries']
|
||||||
entries.should have(1).items
|
entries.should have(1).items
|
||||||
sale_entry = entries[0]
|
sale_entry = entries[0]
|
||||||
sale_entry["line_items"].should have(1).items
|
sale_entry['recurly_total_in_cents'].should eq(sale.recurly_total_in_cents)
|
||||||
sale_entry["recurly_transactions"].should have(0).items
|
sale_json = sale_entry['sale']
|
||||||
|
sale_json.should_not be_nil
|
||||||
|
sale_json["line_items"].should have(1).items
|
||||||
|
|
||||||
|
|
||||||
transaction = FactoryGirl.create(:recurly_transaction_web_hook, invoice_id: sale.recurly_invoice_id, transaction_type: RecurlyTransactionWebHook::VOID)
|
transaction = FactoryGirl.create(:recurly_transaction_web_hook, invoice_id: sale.recurly_invoice_id, transaction_type: RecurlyTransactionWebHook::VOID, user: user, transaction_at: 1.minute.from_now)
|
||||||
|
|
||||||
get :index, { :format => 'json'}
|
get :index, { :format => 'json'}
|
||||||
response.should be_success
|
response.should be_success
|
||||||
body = JSON.parse(response.body)
|
body = JSON.parse(response.body)
|
||||||
body['next_page'].should be_nil
|
body['next_page'].should be_nil
|
||||||
entries = body['entries']
|
entries = body['entries']
|
||||||
entries.should have(1).items
|
entries.should have(2).items
|
||||||
sale_entry = entries[0]
|
void_entry = entries[0]
|
||||||
sale_entry["line_items"].should have(1).items
|
void = void_entry['transaction']
|
||||||
sale_entry["recurly_transactions"].should have(1).items
|
void.should_not be_nil
|
||||||
|
void['amount_in_cents'].should eq(199)
|
||||||
|
sale_entry = entries[1]
|
||||||
|
sale_json = sale_entry['sale']
|
||||||
|
sale_json.should_not be_nil
|
||||||
|
sale_json["line_items"].should have(1).items
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Loading…
Reference in New Issue