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 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
@@ -0,0 +1,3 @@
1
+ name,card_number,pin,balance,card_blocked
2
+ alex,123456789011,MTIzNA==,7500,false
3
+ vincent,123456789012,MTExMQ==,10000,false
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
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+ require 'base64'
3
+ require_relative 'atm'
4
+ require 'highline/import'
5
+ require 'colorize'
6
+
7
+ module ATM
8
+ def self.start
9
+ Atm.new
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ transaction_number,card_number,type,time,amount,status
2
+ 1,123456789012,Withdrawl,23/03/2022 12:05:36:am,102,Fail
3
+ 2,123456789011,Withdrawl,23/03/2022 12:21:12:pm,500,Success
@@ -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: []