Module: Auth::Concerns::Shopping::PaymentConcern

Extended by:
ActiveSupport::Concern
Includes:
ChiefModelConcern, OwnerConcern
Included in:
Shopping::Payment
Defined in:
app/models/auth/concerns/shopping/payment_concern.rb

Overview

NEED A SEPERATE MODEL THAT IMPLEMENTS IT

Defined Under Namespace

Modules: ClassMethods

Instance Method Summary collapse

Instance Method Details

#as_json(options = {}) ⇒ Object



607
608
609
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 607

def as_json(options={})
	super(options).merge({:payment_receipt => self.payment_receipt,:cash_change => self.cash_change})
end

#calculate_changeObject

sets the change to be given to the customer @return : returns nothing, just sets the cash_change attribute.



315
316
317
318
319
320
321
322
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 315

def calculate_change
	## by this point in time the cart has already been set, and prepared, so we know the total pending amount. 
	if self.amount > self.cart.cart_pending_balance
		self.cash_change = self.amount - self.cart.cart_pending_balance
	else
		self.cash_change = 0
	end
end

#card_and_cheque_payment_provides_proofObject



593
594
595
596
597
598
599
600
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 593

def card_and_cheque_payment_provides_proof
	## it is not directly possible to create a card / cheque payment as successfull even as an administrator
	## you have to first create an image resource, and it will check for that in this def, to exist
	## so search for an image resource, that has the payment id of this payment.
	## eg , add this error.

	##self.errors.add("payment_type","you have to upload an image of the card mahine receipt/cheque, to approve this payment.")
end

#card_callback(params, &block) ⇒ Object

the if new_record? is added so that the callback is done only when the payment is first made and not every time the payment is updated



346
347
348
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 346

def card_callback(params,&block)
	
end

#cart_not_emptyObject

validation



516
517
518
519
520
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 516

def cart_not_empty
	return if self.refund == true
	self.errors.add(:cart,"cart has to have some items in order to make a payment") if !self.cart.has_items?

end

#cash_callback(params, &block) ⇒ Object

the if new_record? is added so that the callback is done only when the payment is first made and not every time the payment is updated calculate the change make the amount equal to the pending balance if it is excesive.



304
305
306
307
308
309
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 304

def cash_callback(params,&block)
	if self.new_record?
		calculate_change
		self.amount = self.cart.cart_pending_balance if payment_excessive?
	end
end

#check_owner_matchesObject



602
603
604
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 602

def check_owner_matches
	self.errors.add("cart_id","the cart id and payment are being created by different users.") if (owner_matches(self.cart) == false)
end

#cheque_callback(params, &block) ⇒ Object

the if new_record? is added so that the callback is done only when the payment is first made and not every time the payment is updated



325
326
327
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 325

def cheque_callback(params,&block)
	
end

#cheque_or_card_payment_not_excessiveObject

validation



510
511
512
513
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 510

def cheque_or_card_payment_not_excessive
	
	self.errors.add(:amount,"payment is excessive") if payment_excessive? && (is_cheque? || is_card?) && !refund
end

#discount_callback(params, &block) ⇒ Object



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
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 371

def discount_callback(params,&block)
	
	## the callback should fire on create/update, so new_record checking is not required.

	## first check if the discount id exists -> get the discount object.
	
	#begin
	
		self.discount = Auth.configuration.discount_class.constantize.find(discount_id)

		#puts "discount is: #{self.discount}"


		if self.discount.requires_verification == true
			#puts "detected discount requires verification"
			self.payment_status = Auth.configuration.discount_class.constantize.get_payment_status(self,discount_id)
			#puts "the payment status is detected as: #{self.payment_status}"
		else
			## what about floating discount codes?
			## can a user use them repeatedly?
			self.payment_status = Auth.configuration.discount_class.constantize.use_discount(self.discount,self)
		end

		## now also set the payment amount to be equal to the discount amount or the discount percentage whichever works out be greater.
		## first preference is given to check the discount amount.
		
		if self.discount.discount_amount > 0
			self.amount = self.discount.discount_amount
			
		elsif self.discount.discount_percentage > 0
			self.amount = self.cart.cart_pending_balance*self.discount.discount_percentage
		else
			self.amount = 0
		end

		##finally ensure its not more than the cart_pending_balance
		self.amount = self.cart.cart_pending_balance if self.amount > self.cart.cart_pending_balance

	#rescue
	#	self.payment_status = 0
	#end

end

#gateway_callback(params, &block) ⇒ Object

override this method depending upon the gateway that you use.



363
364
365
366
367
368
369
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 363

def gateway_callback(params,&block)
	## if its a new_record we don't do any callback, because the payment doesnt exist to check it .
	## if the user has passed in is_verify_payment, we still don;t do this callback, because 
	return if (self.new_record? || self.is_verify_payment == "true") 

	yield if block_given?
end

#get_cart_nameObject

used in pay_u_money_helper.rb



264
265
266
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 264

def get_cart_name
	self.cart.nil? ? "shopping_cart" : (self.cart.name.nil? ? "shopping_cart" : self.cart.name)
end

#is_card?Boolean

Returns:

  • (Boolean)


276
277
278
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 276

def is_card?
	payment_type && payment_type == "card"
end

#is_cash?Boolean

Returns:

  • (Boolean)


272
273
274
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 272

def is_cash?
	payment_type && payment_type == "cash"
end

#is_cheque?Boolean

Returns:

  • (Boolean)


280
281
282
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 280

def is_cheque?
	payment_type && payment_type == "cheque"
end

#is_gateway?Boolean

Returns:

  • (Boolean)


268
269
270
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 268

def is_gateway?
	payment_type && payment_type == "gateway"
end

#payment_callback(type, params, &block) ⇒ Object



284
285
286
287
288
289
290
291
292
293
294
295
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 284

def payment_callback(type,params,&block)
	
	if self.refund
		self.send("refund_callback",params,&block) 
	elsif self.discount_id
		self.send("discount_callback",params,&block)
	else
		self.send("#{type}_callback",params,&block) if self.respond_to? "#{type}_callback"
	end

	yield if block_given?
end

#payment_excessive?Boolean

Returns:

  • (Boolean)


297
298
299
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 297

def payment_excessive?
	self.amount > self.cart.cart_pending_balance && self.amount > 0
end

#payment_failedObject



350
351
352
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 350

def payment_failed
	payment_status && payment_status == 0
end

#payment_pendingObject



358
359
360
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 358

def payment_pending
	!payment_status
end

#payment_satisfies_minimum_payment_requirementObject

validation



585
586
587
588
589
590
591
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 585

def payment_satisfies_minimum_payment_requirement
	self.cart.prepare_cart
	puts "the minimum payment amoutn is:"
	puts self.cart.cart_minimum_payable_amount
	return if (self.refund == true || self.discount)  
	self.errors.add("amount","payment amount is not sufficient") if (self.cart.cart_minimum_payable_amount.nil? || (self.cart.cart_minimum_payable_amount > self.amount))
end

#payment_successObject



354
355
356
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 354

def payment_success
	payment_status && payment_status == 1
end

#physical_payment?Boolean

Returns:

  • (Boolean)


416
417
418
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 416

def physical_payment?
	is_card? || is_cash? || is_cheque?
end

#refresh_refundObject

basically checks if there is any refund that was accepted after this refund_request was created. then in that case sets this refund as failed. this is basically done because while normally, whenever a refund is accepted, all other pending refunds are updated as failed, but suppose that that operation does not complete and some refunds are left still pending. then in the controller update action, this method is called on the payment.



234
235
236
237
238
239
240
241
242
243
244
245
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 234

def refresh_refund
	
	if self.refund && self.payment_status.nil?
		
		already_accepted_refunds = self.class.where(:refund => true, :payment_status => 1, :updated_at => { :$gte => self.created_at})
		
		if already_accepted_refunds.size > 0
			
			self.refund_failed
		end
	end
end

#refund_approved_if_cart_pending_balance_is_equal_to_refund_amountObject

validation



558
559
560
561
562
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 558

def refund_approved_if_cart_pending_balance_is_equal_to_refund_amount
	if payment_status_changed? && payment_status == 1 && refund
		self.errors.add("payment_status","you cannot authorize a refund since the amount you entered is wrong") if self.cart.cart_pending_balance != self.amount
	end
end

#refund_callback(params, &block) ⇒ Object



330
331
332
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 330

def refund_callback(params,&block)
	
end

#refund_created_or_approved_only_if_balance_is_negativeObject

validation



546
547
548
549
550
551
552
553
554
555
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 546

def refund_created_or_approved_only_if_balance_is_negative
	if refund
		## in case the admin wants to mark a refund as failed.
		if payment_status == 0 && payment_status_changed?
		
		else
			self.errors.add("payment_status","you cannot authorize a refund since the pending balance is positive.") if self.cart.cart_pending_balance >= 0
		end
	end
end

#refund_created_or_approved_only_if_sum_of_discount_payments_does_not_cover_cart_pending_balanceObject

validation



565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 565

def refund_created_or_approved_only_if_sum_of_discount_payments_does_not_cover_cart_pending_balance

	if refund

		## get the approved discount payments

		## then check the sum of those payments.
		discount_sum = self.class.get_sum_of_discount_payments(self.cart_id)

		if self.cart.cart_pending_balance < 0
			if discount_sum > self.cart.cart_pending_balance*-1
				self.errors.add("amount","the discounts you availed, cover the need for the refund.")
			end
		end

	end

end

#refund_failedObject



340
341
342
343
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 340

def refund_failed
	self.amount = 0
	self.payment_status = 0
end

#refund_successObject



334
335
336
337
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 334

def refund_success
	self.amount = self.cart.refund_amount
	self.payment_status = 1
end

#set_cart(cart_id) ⇒ Object

finds the cart that this payment refers to sets it to an attr_accessor called cart prepares the cart(refer to cart concern for a description of this method)



443
444
445
446
447
448
449
450
451
452
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 443

def set_cart(cart_id)	
	
	
	self.cart = Auth.configuration.cart_class.constantize.find(cart_id)

	
	self.cart.prepare_cart
	

end

#set_payment_receiptObject

returns the cart_item ids which were accepted due to this payment. called after_save callback. called in show action of controller. return



251
252
253
254
255
256
257
258
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 251

def set_payment_receipt
	self.payment_receipt = {:current_payment => [], :cart => {}}
	Auth.configuration.cart_item_class.constantize.where(:accepted_by_payment_id => self.id.to_s).each do |c_item|
		self.payment_receipt[:current_payment] <<  c_item
	end
	set_cart(self.cart_id) if self.cart.nil?
	self.payment_receipt[:cart] = self.cart.prepare_receipt
end

#update_cart_items_acceptedObject

is called on payment_status_changed check whether this payment was already registered on the cart as success or failed. and then debit/credit. return : true/false depending on whether all the cart items could be successfully updated or not.



458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 458

def update_cart_items_accepted
	
	if payment_status_changed?

		if payment_status == 1
			self.cart.cart_credit+= self.amount
		elsif payment_status == 0 && payment_status_was == 1
			
			self.cart.cart_credit-= self.amount
		else

		end

	

		cart_item_update_results = self.cart.get_cart_items.map{|cart_item| 
			cart_item.signed_in_resource = self.signed_in_resource
			## first all the expected cart items should exist
			## then they should all get saved
			## none of them should be already accepted.
			## if all these conditions are satisfied.
			## then we can say that nothing else has happedn
			## we do an atomic request
			## where(item_id => whatever, accepted => false).set(accepted => true)
			## if this fails for even one, then the payment fails.
			## and all the remaining cart items -> can be refreshed to show that they are not accepted
			## refresh will say -> where(:payment_id => x, and status = acceptd)
			## so if some other payment gets in the way, either it will fail or this will fail, so it works.
			cart_item.set_accepted(self,nil)
		}.compact.uniq
		self.errors.add(:cart,"cart item status could not be updated") if cart_item_update_results[0] == false
	
	else
		if (payment_status == 0 || payment_status == 1)
			cart_item_update_results = self.cart.get_cart_items.map{|cart_item|
				#puts "now mapping cart item"
				#puts cart_item.id.to_s 
				cart_item.signed_in_resource = self.signed_in_resource
				res = cart_item.set_accepted(self,nil)
				res
			}			 
		end
	end
end

#verify_paymentObject



421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
# File 'app/models/auth/concerns/shopping/payment_concern.rb', line 421

def verify_payment


	if self.new_record?
		return nil
	else
		if self.is_verify_payment == "true"
			if self.payment_pending
				return true
			else
				return nil
			end
		else
			return nil
		end
	end
	
end