atm_program 1.4.1.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/account.csv +3 -0
- data/lib/account.rb +24 -0
- data/lib/atm.rb +158 -0
- data/lib/atm_program.rb +11 -0
- data/lib/transaction.csv +3 -0
- data/lib/transaction.rb +137 -0
- data/lib/validation.rb +49 -0
- metadata +78 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6e60dda1416ccfeb905bf97486c26c9df458d26a09762cbbb4ddafb77f539044
|
4
|
+
data.tar.gz: c11852c94b28ab86b612018c28d9718c929daf79d721fe25b2879dd5488a3233
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9a10f7d97f1bb8f0a55b1b7a4d0af5c8525f231d13b095155e6bed0ac6e5c4c963d20284dfbd6e1ed32d80d298e0b89a580994d2cac9e9b74cd192c893b6c2c3
|
7
|
+
data.tar.gz: 51ebcdffce77ab80ba62558cdfcc962277c1bcc55134f6ee05213f076b866ce2aab43da093360e066586a835d95478ffbd220167c5028359aaf593ee30efe605
|
data/lib/account.csv
ADDED
data/lib/account.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'csv'
|
4
|
+
# class Account
|
5
|
+
class Account
|
6
|
+
attr_accessor :name, :card_number, :pin, :balance, :transactions, :card_blocked
|
7
|
+
|
8
|
+
def initialize(name, card_number, pin, balance, card_blocked)
|
9
|
+
@name = name
|
10
|
+
@card_number = card_number
|
11
|
+
@pin = pin
|
12
|
+
@balance = balance
|
13
|
+
@card_blocked = card_blocked
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.find_by_card_number(card_number)
|
17
|
+
CSV.table('/account.csv').each do |entry|
|
18
|
+
if entry[:card_number] == card_number
|
19
|
+
return new(entry[:name], entry[:card_number], entry[:pin], entry[:balance], entry[:card_blocked])
|
20
|
+
end
|
21
|
+
end
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
end
|
data/lib/atm.rb
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'account'
|
4
|
+
require_relative 'validation'
|
5
|
+
require_relative 'transaction'
|
6
|
+
require 'csv'
|
7
|
+
require 'base64'
|
8
|
+
|
9
|
+
# class ATM
|
10
|
+
class Atm
|
11
|
+
include Validation
|
12
|
+
def initialize
|
13
|
+
welcome_screen
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def thank_you
|
19
|
+
puts "\nThank You for using the ATM"
|
20
|
+
sleep(2)
|
21
|
+
welcome_screen
|
22
|
+
end
|
23
|
+
|
24
|
+
def clear
|
25
|
+
sleep(4)
|
26
|
+
puts `clear`
|
27
|
+
end
|
28
|
+
|
29
|
+
def welcome_screen(str = nil)
|
30
|
+
thank_you if str == :exit
|
31
|
+
loop do
|
32
|
+
clear
|
33
|
+
print "---------------------------- Welcome to the ATM ----------------------------\n\n".colorize(:light_green), 'Enter card number => '
|
34
|
+
@card_number = gets.chomp.to_i
|
35
|
+
get_current_account(@card_number)
|
36
|
+
puts "Hello, #{@current_account.name.capitalize}\n\n"
|
37
|
+
display_options(:initial_options) unless card_blocked?
|
38
|
+
thank_you
|
39
|
+
end
|
40
|
+
rescue Interrupt
|
41
|
+
abort("\nThank You for using the ATM")
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_current_account(card_number)
|
45
|
+
return if @current_account = Account.find_by_card_number(card_number)
|
46
|
+
|
47
|
+
puts 'Card not valid'
|
48
|
+
thank_you
|
49
|
+
welcome_screen
|
50
|
+
end
|
51
|
+
|
52
|
+
def display_options(option_type)
|
53
|
+
case option_type
|
54
|
+
when :initial_options
|
55
|
+
puts "\n1. Banking", '2. Mini Statement', '3. Change Pin', '4. Request Chequebook', '5. Exit', "\nSelect option :"
|
56
|
+
user_choice = Integer(gets.chomp)
|
57
|
+
execute_initial_option(user_choice)
|
58
|
+
when :banking_options
|
59
|
+
puts "\n1. Withdrawl", '2. Balance', '3. Deposit', '4. Fast Cash', '5. Back', '6. Exit', "\nSelect option :"
|
60
|
+
user_choice = Integer(gets.chomp)
|
61
|
+
execute_banking_option(user_choice)
|
62
|
+
end
|
63
|
+
rescue ArgumentError
|
64
|
+
puts 'Please enter your option in number.'
|
65
|
+
display_options(option_type)
|
66
|
+
end
|
67
|
+
|
68
|
+
def execute_initial_option(option)
|
69
|
+
case option
|
70
|
+
when 1 then display_options(:banking_options)
|
71
|
+
when 2 then mini_statement
|
72
|
+
when 3 then Transaction.new(@current_account, :'Change Pin')
|
73
|
+
when 4 then Transaction.new(@current_account, :'Request Chequebook')
|
74
|
+
when 5 then welcome_screen(:exit)
|
75
|
+
else
|
76
|
+
puts "#{option} is not a right option", 'Please select the righ option.'
|
77
|
+
display_options(:initial_options)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def execute_banking_option(option)
|
82
|
+
case option
|
83
|
+
when 1 then Transaction.new(@current_account, :Withdrawl, take_amount(:Withdrawl))
|
84
|
+
when 2 then display_balance
|
85
|
+
when 3 then Transaction.new(@current_account, :Deposit, take_amount(:Deposit))
|
86
|
+
when 4 then display_fast_cash_options
|
87
|
+
when 5 then display_options(:initial_options)
|
88
|
+
when 6 then welcome_screen(:exit)
|
89
|
+
else
|
90
|
+
puts "#{option} is not a right option", "Please select the righ option.\n"
|
91
|
+
display_options(:banking_options)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def take_amount(transaction_type)
|
96
|
+
case transaction_type
|
97
|
+
when :Withdrawl
|
98
|
+
available_denominations = [100, 200, 500]
|
99
|
+
puts "\nAvailable denominations are =>\t#{available_denominations[0]}\t#{available_denominations[1]}\t#{available_denominations[2]}\n\n"
|
100
|
+
puts "\nPlease enter amount in multiples of available denominations:"
|
101
|
+
Integer(gets.chomp)
|
102
|
+
when :Deposit
|
103
|
+
puts 'Enter amount:'
|
104
|
+
Integer(gets.chomp)
|
105
|
+
end
|
106
|
+
rescue ArgumentError
|
107
|
+
puts 'Please enter amount in numbers.'
|
108
|
+
take_amount(transaction_type)
|
109
|
+
end
|
110
|
+
|
111
|
+
def display_balance
|
112
|
+
puts "\nBalance => #{@current_account.balance}\n\n" if valid_pin?
|
113
|
+
end
|
114
|
+
|
115
|
+
def mini_statement
|
116
|
+
return unless valid_pin?
|
117
|
+
|
118
|
+
transactions = []
|
119
|
+
CSV.table('/transaction.csv').each do |row|
|
120
|
+
next unless row[:card_number] == @current_account.card_number && row[:status] == 'Success'
|
121
|
+
|
122
|
+
transaction_number = row[:transaction_number].to_s.rjust(4, '0')
|
123
|
+
transactions.append(row[:amount].nil? ? "#{transaction_number} #{row[:time]} #{row[:type]}" : "#{transaction_number} #{row[:time]} #{row[:type]} of Rs =>#{row[:amount]}")
|
124
|
+
next
|
125
|
+
end
|
126
|
+
puts transactions.empty? ? "You don't have any Transactions" : transactions.last(5)
|
127
|
+
sleep(3)
|
128
|
+
end
|
129
|
+
|
130
|
+
def display_fast_cash_options
|
131
|
+
puts '1. 1000', '2. 2000', '3. 5000', '4. 10000', '5. Back', '6. Exit', "\nselect option => "
|
132
|
+
execute_fast_cash(Integer(gets.chomp))
|
133
|
+
rescue ArgumentError
|
134
|
+
puts 'Please enter your option in number:'
|
135
|
+
display_fast_cash_options
|
136
|
+
end
|
137
|
+
|
138
|
+
def execute_fast_cash(option)
|
139
|
+
case option
|
140
|
+
when 1 then Transaction.new(@current_account, :Withdrawl, 1_000)
|
141
|
+
when 2 then Transaction.new(@current_account, :Withdrawl, 2_000)
|
142
|
+
when 3 then Transaction.new(@current_account, :Withdrawl, 5_000)
|
143
|
+
when 4 then Transaction.new(@current_account, :Withdrawl, 10_000)
|
144
|
+
when 5 then display_options(:banking_options)
|
145
|
+
when 6 then welcome_screen
|
146
|
+
else
|
147
|
+
puts "#{option} is not a right option", 'Please select the righ option.'
|
148
|
+
display_fast_cash_options
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def take_pin
|
153
|
+
Integer(ask('Enter your Pin:') { |q| q.echo = '*' })
|
154
|
+
rescue ArgumentError
|
155
|
+
puts 'Please enter pin in numbers'
|
156
|
+
take_pin
|
157
|
+
end
|
158
|
+
end
|
data/lib/atm_program.rb
ADDED
data/lib/transaction.csv
ADDED
data/lib/transaction.rb
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'validation'
|
4
|
+
# class Transaction
|
5
|
+
class Transaction
|
6
|
+
include Validation
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def initialize(current_account, type, amount = nil)
|
11
|
+
@current_account = current_account
|
12
|
+
@type = type
|
13
|
+
@amount = amount
|
14
|
+
@transaction_number = File.readlines('/transaction.csv').length
|
15
|
+
@row = "#{@transaction_number},#{@current_account.card_number},#{@type},#{Time.now.strftime('%d/%m/%Y %I:%M:%S:%P')},#{@amount},"
|
16
|
+
validate_type if valid_pin?
|
17
|
+
end
|
18
|
+
|
19
|
+
def validate_type
|
20
|
+
case @type
|
21
|
+
when :Withdrawl then withdrawl
|
22
|
+
when :Deposit then deposit
|
23
|
+
when :'Change Pin' then change_pin
|
24
|
+
when :'Request Chequebook' then request_chequebook
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def sufficient_balance?
|
29
|
+
return true if @current_account.balance >= @amount
|
30
|
+
|
31
|
+
puts 'Insufficient balance'
|
32
|
+
@status = 'Fail'
|
33
|
+
update_transaction_file(@row << @status << "\n")
|
34
|
+
false
|
35
|
+
end
|
36
|
+
|
37
|
+
def withdrawl
|
38
|
+
return unless sufficient_balance?
|
39
|
+
|
40
|
+
if amount_in_multiples_of_available_denominations?(@amount)
|
41
|
+
@status = 'Success'
|
42
|
+
puts "Successfully withdrawl of Rs #{@amount}"
|
43
|
+
update_transaction_file(@row << @status << "\n")
|
44
|
+
update_account_file(:Withdrawl, amount: @amount)
|
45
|
+
else
|
46
|
+
@status = 'Fail'
|
47
|
+
update_transaction_file(@row << @status << "\n")
|
48
|
+
end
|
49
|
+
rescue Interrupt
|
50
|
+
rescue_interrupt
|
51
|
+
end
|
52
|
+
|
53
|
+
def deposit
|
54
|
+
@status = 'Success'
|
55
|
+
update_account_file(:Deposit, amount: @amount)
|
56
|
+
puts "Successfully deposit of Rs #{@amount}"
|
57
|
+
update_transaction_file(@row << @status << "\n")
|
58
|
+
rescue Interrupt
|
59
|
+
rescue_interrupt
|
60
|
+
end
|
61
|
+
|
62
|
+
def change_pin
|
63
|
+
pins = take_change_pins
|
64
|
+
if pins.first == pins.last
|
65
|
+
update_account_file(@type, pin: Base64.strict_encode64(pins.first.to_s))
|
66
|
+
@status = 'Success'
|
67
|
+
puts 'Successfully pin changed. '
|
68
|
+
else
|
69
|
+
puts 'New pin and confirm pin did not matched'
|
70
|
+
@status = 'Fail'
|
71
|
+
end
|
72
|
+
update_transaction_file(@row << @status << "\n")
|
73
|
+
rescue Interrupt
|
74
|
+
rescue_interrupt
|
75
|
+
end
|
76
|
+
|
77
|
+
def take_pin
|
78
|
+
Integer(ask('Enter your Pin:') { |q| q.echo = '*' })
|
79
|
+
rescue ArgumentError
|
80
|
+
puts 'Please enter pin in numbers'
|
81
|
+
take_pin
|
82
|
+
end
|
83
|
+
|
84
|
+
def take_change_pins
|
85
|
+
new_pin = Integer(ask('Enter new pin:') { |q| q.echo = '*' })
|
86
|
+
if valid_pin_length?(new_pin)
|
87
|
+
confirm_pin = Integer(ask('Enter confirm pin:') { |q| q.echo = '*' })
|
88
|
+
[new_pin, confirm_pin]
|
89
|
+
else
|
90
|
+
puts 'pin must be 4 digits.'
|
91
|
+
take_change_pins
|
92
|
+
end
|
93
|
+
rescue ArgumentError
|
94
|
+
puts 'Please enter pin in numbers'
|
95
|
+
take_change_pins
|
96
|
+
end
|
97
|
+
|
98
|
+
def request_chequebook
|
99
|
+
@status = 'Success'
|
100
|
+
puts "Hey #{@current_account.name.capitalize}, Your request for chequebook is accepted"
|
101
|
+
update_transaction_file(@row << @status << "\n")
|
102
|
+
rescue Interrupt
|
103
|
+
rescue_interrupt
|
104
|
+
end
|
105
|
+
|
106
|
+
def update_account_file(transaction_type, amount: nil, pin: nil)
|
107
|
+
data = CSV.table('/account.csv')
|
108
|
+
data.each do |entry|
|
109
|
+
next unless entry[:card_number] == @current_account.card_number
|
110
|
+
|
111
|
+
case transaction_type
|
112
|
+
when :Withdrawl then entry[:balance] -= amount
|
113
|
+
when :Deposit then entry[:balance] += amount
|
114
|
+
when :'Change Pin' then entry[:pin] = pin
|
115
|
+
end
|
116
|
+
File.write('/account.csv', data)
|
117
|
+
break
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def update_transaction_file(data)
|
122
|
+
File.open('/transaction.csv', 'a') do |row|
|
123
|
+
row << data
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def rescue_interrupt
|
128
|
+
thank_you
|
129
|
+
@status = 'Fail'
|
130
|
+
update_transaction_file(@row << @status << "\n")
|
131
|
+
end
|
132
|
+
|
133
|
+
def thank_you
|
134
|
+
puts "\nThank You for using the ATM"
|
135
|
+
sleep(2)
|
136
|
+
end
|
137
|
+
end
|
data/lib/validation.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# module Validation
|
4
|
+
module Validation
|
5
|
+
|
6
|
+
def card_blocked?
|
7
|
+
if @current_account.card_blocked == 'true'
|
8
|
+
|
9
|
+
puts 'Your card is Blocked, Please contact your branch'
|
10
|
+
welcome_screen
|
11
|
+
else
|
12
|
+
false
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def valid_pin?
|
17
|
+
3.times do |n|
|
18
|
+
pin = Base64.strict_encode64(take_pin.to_s)
|
19
|
+
return true if @current_account.pin == pin
|
20
|
+
|
21
|
+
puts "Incorrect Pin\n\n"
|
22
|
+
next unless n == 2
|
23
|
+
|
24
|
+
@accounts_table = CSV.table('/account.csv').each do |account|
|
25
|
+
if account[:card_number] == @current_account.card_number
|
26
|
+
account[:card_blocked] = 'true'
|
27
|
+
break
|
28
|
+
end
|
29
|
+
end
|
30
|
+
File.write('/account.csv', @accounts_table)
|
31
|
+
puts "You have entered wrong pin 3 times\nnow your card is blocked contact your bank for more details.."
|
32
|
+
return false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def amount_in_multiples_of_available_denominations?(amount)
|
37
|
+
available_denominations = [100, 200, 500]
|
38
|
+
if (amount % available_denominations[0]).zero? || (amount % available_denominations[1]).zero? || (amount % available_denominations[2]).zero?
|
39
|
+
true
|
40
|
+
else
|
41
|
+
puts "The amount you entered is not multiple of available denominations\n\n"
|
42
|
+
false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def valid_pin_length?(pin)
|
47
|
+
pin.to_s.length == 4
|
48
|
+
end
|
49
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: atm_program
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.4.1.pre
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Zaid Shaikh
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-03-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: colorize
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.8.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.8.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: highline
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.0.3
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.0.3
|
41
|
+
description:
|
42
|
+
email: 45shaikhzaid@gmail.com
|
43
|
+
executables: []
|
44
|
+
extensions: []
|
45
|
+
extra_rdoc_files: []
|
46
|
+
files:
|
47
|
+
- lib/account.csv
|
48
|
+
- lib/account.rb
|
49
|
+
- lib/atm.rb
|
50
|
+
- lib/atm_program.rb
|
51
|
+
- lib/transaction.csv
|
52
|
+
- lib/transaction.rb
|
53
|
+
- lib/validation.rb
|
54
|
+
homepage: https://github.com/shaikh21/ATM
|
55
|
+
licenses:
|
56
|
+
- MIT
|
57
|
+
metadata:
|
58
|
+
documentation_uri: https://github.com/shaikh21/ATM
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 2.7.0
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">"
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 1.3.1
|
73
|
+
requirements: []
|
74
|
+
rubygems_version: 3.3.3
|
75
|
+
signing_key:
|
76
|
+
specification_version: 4
|
77
|
+
summary: This GEM contains the simple ATM program.
|
78
|
+
test_files: []
|