# Creating an Accounting Program in Julia, for Pluto

**URL:** <https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227>\
**Category:** Finance and Economics\
**Tags:** question, dataframes, function, pluto\
**Created:** [June 1, 2021, 8:38pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227 "2021-06-01T20:38:12Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [June 2, 2021, 5:03pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227/21 "2021-06-02T17:03:50Z")

</div>

You can `println` your error message, and return `false`.  
Or you can return an Integer, 0 for no error, 1,2,3,… for all the errors which you handle.  
These are thoughts which can be dependend on the future use of this function.  
For now, choose what’s easiest for you (but type stable).

Don’t forget issue “global variables”.

---

<div class="post-metadata">

**Author:** ![brett\_knoss](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brett_knoss/32/13050_2.png) [@brett\_knoss](https://discourse.julialang.org/u/brett_knoss)\
**Post date:** [June 2, 2021, 5:06pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227/22 "2021-06-02T17:06:39Z")

</div>

Print is a great solution, unfortunately Pluto doesn’t show printed messages, not as big a fan of the number idea, but it would indeed work.

I haven’t forgot about the global varible issue, and I think it’s a better issue, but I want to get this sorted first.

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [June 2, 2021, 5:10pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227/23 "2021-06-02T17:10:57Z")

</div>

I see, I didn’t check in Pluto.  
So, you can return a tuple of bool and string: (false,“my error”) in case of an error, and (true,“”) or (true,“no error”) in case of no error.

---

<div class="post-metadata">

**Author:** ![brett\_knoss](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brett_knoss/32/13050_2.png) [@brett\_knoss](https://discourse.julialang.org/u/brett_knoss)\
**Post date:** [June 2, 2021, 5:14pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227/24 "2021-06-02T17:14:49Z")

</div>

I need to look up bools, I have a vauge idea on how to write a bool, but I’m not entirely familiar with the types.

---

<div class="post-metadata">

**Author:** ![lungben](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lungben/32/12314_2.png) [@lungben](https://discourse.julialang.org/u/lungben)\
**Post date:** [June 2, 2021, 5:16pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227/25 "2021-06-02T17:16:03Z")

</div>

> [@oheil](#):
>
> ```julia-auto
> ledger=DataFrame(
> date=[""],
> chequing=[0],
> expenses=[0],
> income=[0])
> 
> ```

I would define the `date` field of type `Date`, Dates as strings are a nightmare (no validation, bad performance, etc.).  
When you initialize the DataFrame this way, you create one (probably invalid) entry. It would be better to initialize it empty (but with typed columns):

```julia-auto
ledger = DataFrame(date=Date[], chequing=Int[],	expenses=Int[],	income=Int[])

```

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [June 2, 2021, 5:16pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227/26 "2021-06-02T17:16:06Z")

</div>

A bool has just two values: true or false. You can also use integer 0 and 1. Doesn’t matter to much. Important: always returning the same type, e.g. (1,“error”) which is a Tuple{Int,String}.

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [June 2, 2021, 5:20pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227/27 "2021-06-02T17:20:09Z")

</div>

> [@lungben](#):
>
> I would define the `date` field of type `Date` , Dates as strings are a nightmare

Yes, you are right.  
I want the function `ledgertransaction` to be agnostic of these details (at least a bit agnostic, of course some logic must be implemented). But dealing with Date-types at this point is quite a step, so I would postpone it for later.

---

<div class="post-metadata">

**Author:** ![brett\_knoss](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brett_knoss/32/13050_2.png) [@brett\_knoss](https://discourse.julialang.org/u/brett_knoss)\
**Post date:** [June 2, 2021, 5:41pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227/28 "2021-06-02T17:41:18Z")

</div>

I wanted to have an abbreviation for date, instead of numbers, as I feel this can create confusion. I will look through the documentation for Date.jl, and get this set up properly.

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [June 2, 2021, 5:42pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227/29 "2021-06-02T17:42:48Z")

</div>

Good.

---

<div class="post-metadata">

**Author:** ![brett\_knoss](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brett_knoss/32/13050_2.png) [@brett\_knoss](https://discourse.julialang.org/u/brett_knoss)\
**Post date:** [June 2, 2021, 5:57pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227/30 "2021-06-02T17:57:58Z")

</div>

I think check is the easiest thing to start

check = bool{chequing\_amount - debit\_amount!=0,“credit and debit amounts must match”}

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [June 2, 2021, 6:02pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227/31 "2021-06-02T18:02:41Z")

</div>

You are thinking too complex here. It’s easy like:

```julia
function ledgertransaction!( ledger, date, credit_account, credit_amount, debit_account, debit_amount )

    if credit_amount-debit_amount != 0
        return (false, "Error -- credit and debit must match.")
    else if length(date) == 0
        return (false, "Error -- no date entered")
    else ...

    ...
    return (true, "no error)
end

```

---

<div class="post-metadata">

**Author:** ![brett\_knoss](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brett_knoss/32/13050_2.png) [@brett\_knoss](https://discourse.julialang.org/u/brett_knoss)\
**Post date:** [June 2, 2021, 6:04pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227/32 "2021-06-02T18:04:59Z")

</div>

> [@oheil](#):
>
> ` return (false, "Error -- credit and debit must match.")`

Yes, I tend to do that lol. This solution works great.

I believe the next issue you said is a priority is with global and local variables?

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [June 2, 2021, 6:10pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227/33 "2021-06-02T18:10:01Z")

</div>

> [@brett\_knoss](#):
>
> I believe the next issue you said is a priority is with global and local variables?

Yes, I already proposed it with:

```julia
function ledgertransaction!( ledger, date, credit_account, credit_amount, debit_account, debit_amount )

```

Read about it using the docs (link above).  
If you confirm, provide the complete function we have now, same if you not confirm.

---

<div class="post-metadata">

**Author:** ![brett\_knoss](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brett_knoss/32/13050_2.png) [@brett\_knoss](https://discourse.julialang.org/u/brett_knoss)\
**Post date:** [June 2, 2021, 6:17pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227/34 "2021-06-02T18:17:38Z")

</div>

Is this a new function that creates my initial dataframe? I’m not sure I follow from the documentation.

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [June 2, 2021, 6:30pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227/35 "2021-06-02T18:30:58Z")

</div>

Just go ahead and show what you have. We will clean it up if necessary.

---

<div class="post-metadata">

**Author:** ![brett\_knoss](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brett_knoss/32/13050_2.png) [@brett\_knoss](https://discourse.julialang.org/u/brett_knoss)\
**Post date:** [June 2, 2021, 6:52pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227/36 "2021-06-02T18:52:36Z")

</div>

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

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

			else

		
    default_row=Dict("chequing"=>0,"expenses"=>0,"income"=>0)
    spec = Dict(
			"date" => date, 
			credit_account => credit_amount, 
			debit_account => debit_amount)
		
    row = merge(default_row, spec)
    
	push!(ledger,row)
	
	journal_entry=DataFrame(
		                   date=["Jan 1, 2000","","",""],
		                   credited_account=["", credit_account,"",""],
						   debited_account=["","",debit_account,""],
		                   credit=[0,credit_amount,0,0],
		                   debit=[0,0,debit_amount,0],
			               
							#balance=[0,
							 # sum(credit_account),
				              # sum(add_debit_account),
				               # 0]
							#I need to figure out how to calculate my balance
		)

 
				end
			end
		end
	end
end

```

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [June 2, 2021, 7:26pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227/37 "2021-06-02T19:26:24Z")

</div>

No, not yet.

- `journal_entry` we don’t want yet, first steps first
- `default_row` should be named `default_values`
- using `elseif` instead of nested `else if` makes it more readable and less `end`s to use.

If you want to take a peek:

> ****
>
> ```julia
> using DataFrames
> 
> ledger=DataFrame(
> date=[],
> chequing=[],
> expenses=[],
> income=[]);
> 
> function ledgertransaction(
> date,
> credit_account,
> credit_amount,
> debit_account,
> debit_amount
> )
> if credit_amount-debit_amount != 0
> return (false,"Error -- credit and debit must match.")
> elseif 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")
> 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, "no error")
> end
> end
> 
> ```

This is, what we want.  
But still issue “global variables” is not adressed! I explain what it means:

You are using the DataFrame `ledger` inside the function. But it is defined outside of the function. This works, because in Pluto (as in the REPL) `ledger` is implicitly global. This is not the case in modules e.g., this is called soft scope. For details about scope see [Scope of Variables · The Julia Language](https://docs.julialang.org/en/v1/manual/variables-and-scoping/)

Example in a new REPL:

```julia
julia> function test()
          println(i)
       end

julia> test()
ERROR: UndefVarError: i not defined

julia> local i =5
5

julia> test()
ERROR: UndefVarError: i not defined

julia> global i = 5 #works without global in REPL
5

julia> test()
5

```

Our code we develop should work in REPL, Pluto or in a module or script without any changes. It should be as generic as possible. And we want to avoid anything which decreases our performance. The docs say, we should avoid globals. Even we don’t know why, we do it, because it’s easy to avoid, it doesn’t cost anything, it’s just better.

So, what do you suggest to avoid global `ledger`? Hint: `ledger` itself in our Pluto scenario is always global (or we put a local before the definition), but we want our function `ledgertransaction` not to rely on that. We want to have a working `ledgertransaction` even if `ledger` is not global!

---

<div class="post-metadata">

**Author:** ![brett\_knoss](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brett_knoss/32/13050_2.png) [@brett\_knoss](https://discourse.julialang.org/u/brett_knoss)\
**Post date:** [June 2, 2021, 7:52pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227/38 "2021-06-02T19:52:10Z")

</div>

OK, I changed the default\_row to default\_values, and fixed the if statements. I’ll read this over about variables.

---

<div class="post-metadata">

**Author:** ![brett\_knoss](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brett_knoss/32/13050_2.png) [@brett\_knoss](https://discourse.julialang.org/u/brett_knoss)\
**Post date:** [June 2, 2021, 7:55pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227/39 "2021-06-02T19:55:02Z")

</div>

I was over thinking again. I didn’t realise that you were saying ledger should be declared global.

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

function ledgertransaction(
    date,
    credit_account,
    credit_amount,
    debit_account,
    debit_amount
)
	
	check=credit_amount-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 check != 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)
        end
end

```

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [June 2, 2021, 7:58pm UTC](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227/40 "2021-06-02T19:58:09Z")

</div>

> [@brett\_knoss](#):
>
> I didn’t realise that you were saying ledger should be declared global.

Well, I said the opposite: You should use it as it were local!

You missed two other things from my code:

- the return value in the case of no error
- calculating check isn’t necessary, check what I provided (clicking on Details).

[Previous page](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227.md?page=1)

[Next page](https://discourse.julialang.org/t/creating-an-accounting-program-in-julia-for-pluto/62227.md?page=3)
