Metamorphz
Posts: 9
Joined: 25 Feb 2015 09:47

Inventory Aging

Inventory Illusion

Most Profit(Loss) reader especially which are not referring to the Cash Flow report as comparison benchmark are unaware with the increased of current assets account. Inventory is one of the accounts that easily camouflage those profit numbers.

To simply illustrate that, say there's a retail company that operates only in cash both for purchase and sales, don't have any debt and loan. This company start with 1 billion IDR cash capital, buy merchandise for 1 billion IDR, and sell it for 2 billion IDR. Then the company gain 1 billion IDR profit. Now the company use all the money buying the inventory for 2 billion IDR amount. By the end of the period, this company will book 1 billion IDR of starting Capital, 1 billion IDR of profit which reflect to its asset; 2 billion IDR of inventory.

The question then arise, what happened if that 2 billion IDR of inventory turns out can not be sold because it is expired? They have to sell the merchandise as scrap, and suddenly that 2 billion IDR inventory is not worth that amount of money anymore. If the company sell it all as scrap at 200million IDR , by the end of period, the company suddenly have loss position at 800million IDR.

In various scales and sometimes out of periodic control, this thing happened in the companies. Dead stock, unusable stock, expired stock, bad stock which booked in the accounting with its purchase value, are illusions of profit.. Since it is an illusion, it can also be used as fraud account especially for a company that have a lot of inventory traffic. What happened with merchandise stock that don't have expiry date? Keeping stock has its own cost. i.e warehouse cost and interest cost for the money value. As long as that is not a merchandise that have increasing value overtime like wine or smoked meat, the keeping cost can not be compensated with increased revenue of merchandise sales.

Some company as dictate by accounting standard operating procedure, trying to minimize the loss by doing periodic stock taking. But the problem with stock taking is mostly the activity only focus and check whether the stock is there with the correct quantity or not. Hence it solve only book accuracy problem, the illusion problem of inventory value is still there.


Inventory Aging

Since most stock is degrading its value overtime either caused by expiry time or the keeping cost, we can conclude that by monitoring the age of stock can also helping company to prevent its degrading value.

The idea of inventory aging is just as simple as classify and existing inventory based on the time of procurement, and calculate the financial value for each class. However at the floor, the effort and the method is not just as simple as it sound. Especially if the warehouse management strategy is not efficient enough to make sure that the flow of stock is FIFO (First In First Out). But this following idea, will at least giving the big picture of stock condition. The real condition could be worse, but cannot be better than Inventory Aging calculation.


Calculation Technic

Inventory aging calculation, algorithm is as simple as
1. Calculating the current stock value of inventory.
2. Query the last purchased particular stock in total amount that match current stock value.
3. Classify query result based on purchased date.


Step #1 : Calculating current stock value of Inventory

Code: Select all

declare MyAccount cursor local static read_only forward_only for
select b.gl_subcode,sum(b.gl_value) 
	from Accounting.[journal.header] a
	                inner join accounting.[journal.detail] b on a.hdr_id = b.hdr_id 
	where a.gl_date <= @Date and b.acc_no = @AccNo and b.cc_id = @CCID
	group by gl_subcode
this step will generate a query of current stock value at GL group by the Inventory code (Subcode) and put the result into cursor "MyAccount"



Step #2 : Get all GL transaction data from last "increment transaction of inventory" based on transaction date, but only the ones that the summary value match the current stock value

Code: Select all

	open MyAccount
	fetch next from MyAccount into @SubCode,@TargetValue
	while @@Fetch_Status=0
		begin
			if @Sign=sign(@TargetValue)
				begin
					if @Sign<0 --- for Credit account
						insert into @Result select gl_id,case when balance>0 then gl_value+balance else gl_value end
							from
							(select b.gl_id, b.gl_value,@TargetValue-sum(b.gl_value) over (order by a.gl_date desc,b.gl_value) as balance
							from accounting.[journal.header] a
							inner join accounting.[journal.detail] b on a.hdr_id = b.hdr_id
							where a.gl_date <= @Date and b.gl_subcode = @Subcode and b.acc_no = @AccNo and b.cc_id = @CCID and b.gl_value<0
							) a where balance+gl_value<0
					else -- for Debit account
						insert into @Result select gl_id,case when balance<0 then gl_value+balance else gl_value end
							from
							(select b.gl_id, b.gl_value,@TargetValue-sum(b.gl_value) over (order by a.gl_date desc,b.gl_value desc) as balance
							from accounting.[journal.header] a
							inner join accounting.[journal.detail] b on a.hdr_id = b.hdr_id
							where a.gl_date <= @Date and b.gl_subcode = @Subcode and b.acc_no = @AccNo and b.cc_id = @CCID and b.gl_value>0
							) a where balance+gl_value>0

				end
			fetch next from MyAccount into @SubCode,@TargetValue
		end
	close MyAccount
	deallocate MyAccount
this step will generate a query of all related GL detail data id and the GL value, for particular account (which in this case is Inventory account) that the summary value of it will match the summary of current stock value, and put the result into temporary table @Result



Step #3 : Query the GL Id from @Result, pivot based on the age

Code: Select all

	select 
	group_id,
	group_name
	,isnull([1],0) as Period1
	,isnull([2],0) as Period2
	,isnull([3],0) as Period3
	,isnull([4],0) as Period4
	,isnull([1],0)+isnull([2],0)+isnull([3],0) +isnull([4],0) as Total  
	from (
		select * from (
			select 
			d.group_id, e.group_name, a.gl_value,
			case	when datediff(day, c.gl_date, @docdate)>60*3 then 4
					--when 
					else CEILING(CONVERT(DECIMAL,datediff(day, c.gl_date, @docdate))/60) end as dt
			from @Result a
			inner join accounting.[journal.detail] b on a.gl_id = b.gl_id
			inner join accounting.[journal.header] c on b.hdr_id = c.hdr_id
			inner join inventory.[item.master] d on b.gl_subcode = d.item_no
			inner join inventory.[item.group] e on d.group_id = e.group_id
			) a pivot (
		sum(a.gl_value) for
		dt in ([0],[1],[2],[3],[4])
		) as pv
	) a 
this step will produce the Inventory Aging query

NB:
More comprehensive coding can be found in the UDF : [Accounting].[Outstanding.Local.General.Alternate]
Faster performance driven query can be found in the UDF : [Accounting].[Outstanding.Local.General], using cursor and fetch is faster than sub-query.
User avatar
loeischandra
Posts: 25
Joined: 23 Feb 2015 17:04

Re: Inventory Aging

Ilusi Persediaan barang dagang

Sebagian besar orang setelah membaca laporan laba rugi, jarang sekali melakukan penulusuran lebih lanjut dengan membaca laporan Arus Kas sebagai patokan nilai pembanding, sehingga mereka tidak sadar pertambahan nilai aktiva ini bisa menimbulkan suatu masalah yang merugikan perusahaan. Dan akun persediaan barang dagang adalah salah satu akun aktiva yang bisa dengan mudah bermasalah dan mengkamuflase nilai laporan laba rugi itu.

Supaya lebih mudah mengilustrasikan atau menggambarkan, katakan misal ada sebuah perusahaan retail atau pengecer yang beroperasi pada transaksi pembelian dan penjualan saja, sehingga tidak memiliki hutang maupun pinjaman. Nah perusahaan ini memulai usahanya dengan modal sebesar 1 Miliar rupiah, kemudian membeli barang dagangan seharga 1 Miliar rupiah dan menjualnya seharga 2 Miliar rupiah. Jadi sampai disini perusahaan itu mendapatkan laba sebesar 1 Miliar rupiah. Selanjutnya perusahaan ini menggunakan semua uang yang dimiliki untuk membeli persediaan barang dagangan lagi dengan jumlah 2 Miliar rupiah. Di akhir periode, perusahaan akan mencatat bahwa 1 Miliar rupiah sebagai Modal awal, 1 Miliar rupiah sebagai laba yang akhirnya didistribusikan ke aktiva persediaan, dan 2 Miliar rupiah sebagai persediaan barang dagang akhir.

Pertanyaan yang kemudian muncul yakni, apa yang terjadi jika 2 Miliar rupiah dari Persediaan barang dagang tadi ternyata tidak bisa dijual karena batas kadaluwarsa yang sempit atau barang rusak? Merekapun akhirnya harus menjual barang dagangan mereka sebagai barang sisa. Dan persediaan barang dagang pun yang semula senilai 2 Miliar rupiah sekarang menjadi tidak seimbang dengan nilai uangnya. Jika pada akhirnya perusahaan menjual rugi persediaan barang dagangan itu sebagai sisa/potongan dengan harga 200 Juta rupiah. Di akhir periode, perusahaan tersebut harus mencatatkan kerugian 800 Juta rupiah.

Di berbagai kasus dan terkadang hal semacam ini sulit terdeteksi atau dilihat hanya dengan laporan keuangan bulanan, kerugian karena umur persediaan barang dagang sudah banyak tejadi di perusahaan-perusahaan. Stok rusak, stok tidak dapat digunakan, stok kedaluwarsa, dan kualitas stok barang buruk, padahal semua itu dicatat dalam jurnal akuntansi dengan nilai perolehan yang besar, sehingga menjadi sebuah ilusi profit saja di periode selanjutnya. Dan karena sifat ilusi tersebut, hal ini bisa juga digunakan seseorang untuk melakukan penipuan laporan keuangan khususnya pada sebuah perusahaan yang mempunyai lalu lintas persediaan barang yang tinggi sekali.

Nah sekarang, apa yang terjadi jika membeli persediaan barang yang tidak memiliki tanggal kedaluwarsa? Menjaga persediaan seperti ini memiliki biaya sendiri yaitu biaya gudang atau biaya bunga penyimpanan. selama itu bukan sebuah barang dagangan yang bakal naik nilai jualnya seperti contohnya anggur, biaya pemeliharaan dan penyimpanan barang tidak bisa dikompensasikan menggantikan kerugian dengan menaikan pendapatan dari penjualan persediaan barang tersebut.

Sampai saat ini beberapa perusahaan hanya berpegang pada prosedur laporan standard keuangan saja, jadi mereka mencoba untuk mengecilkan kerugian umur persediaan dengan cara mengambil persediaan secara berkala. Tetapi hal ini pun akan mengambil waktu kita hanya untuk fokus untuk memeriksa apakah stok persediaan yang ada dalam jumlah yang benar atau tidak. Dan ini, hanya menyelesaikan sebagian masalah yaitu ketepatan/ akurasi persediaan yang di lapangan dengan pencatatan saja, padahal sebenarnya, masalah ilusi dari nilai persediaan barang masih ada.

Umur Persediaan Barang Dagang

Karena sebagian besar nilai persediaan barang terus turun, baik disebabkan oleh waktu kedaluwarsa atau karena biaya penyimpanan, dapat kita simpulkan bahwa pengawasan terhadap laporan umur persediaan dapat membantu perusahaan untuk mencegah kerugian nilai tersebut.

Ide dari Laporan umur persediaan adalah klasifikasi sederhana dari persediaan yang ada berdasarkan waktu pembelian dan kalkulasi atau perhitungan nilai keuangan dari tiap kategori kelas stock barang. Namun, usaha dan metode ini tidak semudah dan sesederhana seperti yang dibayangkan. Apalagi jika strategi manajemen gudang tidak cukup efisien untuk meyakinkan keakuratan arus stok dengan metode FIFO ( First In First Out). Oleh karena itu ide pada artikel ini memberi gambaran besar tentang masalah persediaan barang yang bisa terjadi. Kondisi sebenarnya di lapangan bisa lebih buruk, tapi tidak akan lebih baik dari pada perhitungan umur persediaan.

Cara perhitungan

Langkah perhitungan laporan umur persediaan memiliki algoritma seperti berikut ini
1. Menghitung persediaan yang tersedia saat ini
2. Melakukan Query dari pembelian terakhir sehingga cocok dengan total nilai stock saat ini
3. Mengelompokkan hasil Query berdasarkan tanggal pembelian

Step #1 : Menghitung persediaan barang saat ini

Code: Select all

declare MyAccount cursor local static read_only forward_only for
select b.gl_subcode,sum(b.gl_value) 
	from Accounting.[journal.header] a
	                inner join accounting.[journal.detail] b on a.hdr_id = b.hdr_id 
	where a.gl_date <= @Date and b.acc_no = @AccNo and b.cc_id = @CCID
	group by gl_subcode
langkah ini akan membuat daftar jumlah persediaan yang ada di GL, dikelompokkan berdasarkan kode persediaan dan meletakkan pada tabel cursor "MyAccount"



Step #2 : Mendapatkan semua transaksi GL dari transaksi terakhir persediaan dari tanggal transaksi, yang cocok dengan jumlah stock saat ini.

Code: Select all

	open MyAccount
	fetch next from MyAccount into @SubCode,@TargetValue
	while @@Fetch_Status=0
		begin
			if @Sign=sign(@TargetValue)
				begin
					if @Sign<0 --- for Credit account
						insert into @Result select gl_id,case when balance>0 then gl_value+balance else gl_value end
							from
							(select b.gl_id, b.gl_value,@TargetValue-sum(b.gl_value) over (order by a.gl_date desc,b.gl_value) as balance
							from accounting.[journal.header] a
							inner join accounting.[journal.detail] b on a.hdr_id = b.hdr_id
							where a.gl_date <= @Date and b.gl_subcode = @Subcode and b.acc_no = @AccNo and b.cc_id = @CCID and b.gl_value<0
							) a where balance+gl_value<0
					else -- for Debit account
						insert into @Result select gl_id,case when balance<0 then gl_value+balance else gl_value end
							from
							(select b.gl_id, b.gl_value,@TargetValue-sum(b.gl_value) over (order by a.gl_date desc,b.gl_value desc) as balance
							from accounting.[journal.header] a
							inner join accounting.[journal.detail] b on a.hdr_id = b.hdr_id
							where a.gl_date <= @Date and b.gl_subcode = @Subcode and b.acc_no = @AccNo and b.cc_id = @CCID and b.gl_value>0
							) a where balance+gl_value>0

				end
			fetch next from MyAccount into @SubCode,@TargetValue
		end
	close MyAccount
	deallocate MyAccount
langkah ini akan mengambil data dari GL berupa data id dan GL Value, untuk akun tertentu (untuk kasus ini yaitu persediaan barang) yang nilai totalnya sesuai dengan persediaan saat ini, dan memasukkan hasilnya ke tabel temporary @Result


Step #3 : Query GL Id dari @Result, kemudian dibuat pivot berdasarkan umut GL Id dari @Result

Code: Select all

	select 
	group_id,
	group_name
	,isnull([1],0) as Period1
	,isnull([2],0) as Period2
	,isnull([3],0) as Period3
	,isnull([4],0) as Period4
	,isnull([1],0)+isnull([2],0)+isnull([3],0) +isnull([4],0) as Total  
	from (
		select * from (
			select 
			d.group_id, e.group_name, a.gl_value,
			case	when datediff(day, c.gl_date, @docdate)>60*3 then 4
					--when 
					else CEILING(CONVERT(DECIMAL,datediff(day, c.gl_date, @docdate))/60) end as dt
			from @Result a
			inner join accounting.[journal.detail] b on a.gl_id = b.gl_id
			inner join accounting.[journal.header] c on b.hdr_id = c.hdr_id
			inner join inventory.[item.master] d on b.gl_subcode = d.item_no
			inner join inventory.[item.group] e on d.group_id = e.group_id
			) a pivot (
		sum(a.gl_value) for
		dt in ([0],[1],[2],[3],[4])
		) as pv
	) a 
langkah ini akan mengeluarkan data Query umur persediaan

NB:
Query yang lebih jelas bisa dilihat di UDF : [Accounting].[Outstanding.Local.General.Alternate]
Untuk hasil lebih cepat bisa dilihat di UDF : [Accounting].[Outstanding.Local.General], menggunakan cursor lebih cepat dari sub-query.

Return to “Inventory”