Creating an Accounting Program in Julia, for Pluto

What do you think is the next thing to work on?

OK, putting it all together and a bit of prettier formatting we have now:

using DataFrames

ledger=DataFrame(
	date=[],
	chequing=[],
	expenses=[],
	income=[]);

function ledgertransaction(
    date,
    credit_account,
    credit_amount,
    debit_account,
    debit_amount
)
	if length(date) == 0
		return (false,"Error -- no date entered")
	elseif !( credit_account in names(ledger) )
		return (false, "Error -- credit account not found.")
	elseif !( debit_account in names(ledger) )
		return (false, "Error -- debit account not found")
	elseif credit_amount-debit_amount != 0			
		return (false,"Error -- credit and debit must match." )
	else
		default_values=Dict("chequing"=>0,"expenses"=>0,"income"=>0)

		spec = Dict(
			"date" => date, 
			credit_account => credit_amount, 
			debit_account => debit_amount)
		row = merge(default_values, spec)
		push!(ledger,row)
	
		return (true, "there  are no errors")	
	end
end

ledgertransaction("Jan 1, 2000","expenses",100,"chequing",100)

You should use these code lines for the further steps.

Well done so far!

Letā€™s take a short break here: Itā€™s important that you understand those issues. What we have learned so far helps to create code which is easy to read. Not for others but at first for you. You need to have readable code for yourself to always see, whats going on. Doing this lets you focus on the important things in coding: the real problems.

I am not sure, if you enjoy those lessons. Of course you are always free to stop this. It only makes sense if you have some fun going through all this!

Now, we have a single one left:

If ledger is local, that means, it is not available currently inside ledgertransaction, so the function would produce an error. How can we overcome this?

3 Likes

Hmmmm, the ledger canā€™t be inside the function,because it would recreate the DataFrame anew, and not save the wanted information.

Iā€™m thinking that if there was a function to create the ledger, that was called inside the transaction function, then the variable ledger would be local. Am I on the right track?

Its, again, easier.

why not doing this?
function ledgertransaction( ledger, date, credit_account, credit_amount, debit_account, debit_amount )

Where does this go? do I have to have something inside?

You provide ledger as a parameter?

Ask, if there is something unclear!

Iā€™m not familiar with parameters.

Thatā€™s not a question, but anyways. functions have parameters. When you call a function you provide values to the function as parameters. See Functions Ā· The Julia Language
Well itā€™s arguments, not parameters, sorry.

So the idea is just, that we provide ledger as an argument to the function.
Arrays ( and DataFrames) are passed to the function as a reference. So the argument ledger is the same as our ā€œglobalā€ ledger when we pass it as argument to the function.
Like:

julia> function test(array)
           array[1]=2
       end
test (generic function with 1 method)

julia> a=[1]
1-element Vector{Int64}:
 1

julia> test(a)
2

julia> a
1-element Vector{Int64}:
 2

Array a is changed by the function.
If functions change their arguments the convention is to name the function with ! :

julia> function test!(array)
           array[1]=2
       end

Can you transfer this information into a new ledgertransaction function?

function ledgertransaction( ledger, date, credit_account, credit_amount, debit_account, debit_amount )
	ledger=DataFrame(
	
    	date=[],
    
		#Assets
	
		chequing=[],
    	
		#Expenses
	
		expenses=[],
    	
		#Revenue
	
		income=[]);
end

You donā€™t need any ledger1.
Whatā€™s your motivation for this?

I was testing things, and I forgot I did that.

 function ledgertransaction!(
		    date,
   	 		credit_account,
    		credit_amount,
    		debit_account,
    		debit_amount
)
	
		default_values=Dict("chequing"=>0,"expenses"=>0,"income"=>0)
    		spec = Dict(
					"date" => date, 
				credit_account => credit_amount, 
				debit_account => debit_amount)
    		row = merge(default_values, spec)
	
           push!(ledger,row)
       end

Why did you create your own package, to manage decimals?

We are not yet at the milestone 1.
A note: A function name which ends with an ! is a convention (Style Guide Ā· The Julia Language) and denotes function, which modify one or all of their arguments.

We enforce the globale ledger to be local with:

local ledger=DataFrame(...

The complete current code is than:

using DataFrames

local ledger=DataFrame(
	date=[],
	chequing=[],
	expenses=[],
	income=[]);

function ledgertransaction(
    date,
    credit_account,
    credit_amount,
    debit_account,
    debit_amount
)
	if length(date) == 0
		return (false,"Error -- no date entered")
	elseif !( credit_account in names(ledger) )
		return (false, "Error -- credit account not found.")
	elseif !( debit_account in names(ledger) )
		return (false, "Error -- debit account not found")
	elseif credit_amount-debit_amount != 0			
		return (false,"Error -- credit and debit must match." )
	else
		default_values=Dict("chequing"=>0,"expenses"=>0,"income"=>0)

		spec = Dict(
			"date" => date, 
			credit_account => credit_amount, 
			debit_account => debit_amount)
		row = merge(default_values, spec)
		push!(ledger,row)
	
		return (true, "there  are no errors")	
	end
end

ledgertransaction("Jan 1, 2000","expenses",100,"chequing",100)

Now you should get an error, hopefully in Pluto too.

Your task is now to overcome this error only by changing the definition of the function ledgertransaction. Hint: you donā€™t need to change the code of the function, only itā€™s arguments (and the name by above convention).

Recommended readings are Scope of Variables Ā· The Julia Language and Functions Ā· The Julia Language .

1 Like