Penyusutan Aset Tetap
Bismillah,
Ini adalah perhitungan penyusutan aset tetap dengan metode garis lurus. Penyusutan per tahun, dengan penambahan umur ekonomis bila ada kapitalisasi terhadap aset tetap tersebut. Saya menuliskan algoritma nya dengan berurutan. Tulisan ini minim keterangan, saya belum punya waktu yang cukup untuk memberikan keterangan-keterangan penting, sehingga mungkin sulit dipahami.
Inti yang ingin saya sampaikan, silahkan dipelajari lebih dalam window functions pada PostgreSQL, karena algoritma ini menggunakan banyak fitur pada window functions tersebut.
Pertama
DROP VIEW IF EXISTS view_penyusutan_108_gb_2021_r2_a1 CASCADE;
CREATE VIEW view_penyusutan_108_gb_2021_r2_a1 AS
SELECT * FROM
(SELECT
gedung_bangunan.id_sub_skpd,
sub_skpd.nama_sub_skpd,
sub_skpd.id_skpd,
skpd.nama_skpd,
skpd.id_lokasi_bidang,
lokasi_bidang.nama_lokasi_bidang,
lokasi_bidang.id_kabupaten,
kabupaten.nama_kabupaten,
kabupaten.id_provinsi,
provinsi.nama_provinsi,
gedung_bangunan.id_mutasi_berkurang,
mutasi_berkurang.mutasi_berkurang,
keadaan_barang.keadaan_barang,
satuan_barang.satuan_barang,
golongan_barang.golongan_barang,
gedung_bangunan.id_golongan_barang,
gedung_bangunan.nama_barang,
LEFT(kode_barang_108.kode_barang_108, 18) kode_barang_108,
LEFT(kode_barang_108.kode_barang_108, 8) kode_l2,
gedung_bangunan.id register,
'' as merk_type,
gedung_bangunan.nomor_dokumen_gedung as no_no,
'' as bahan,
harga_gedung_bangunan.tahun,
CONCAT(SUM(harga_gedung_bangunan.luas_lantai), ' m2') as ukuran_barang,
SUM(harga_gedung_bangunan.harga_bertambah) - SUM(harga_gedung_bangunan.harga_berkurang) harga,
gedung_bangunan.keterangan
FROM
gedung_bangunan as gedung_bangunan, harga_gedung_bangunan as harga_gedung_bangunan, kode_barang_108,
mutasi_berkurang, asal_usul, keadaan_barang, satuan_barang, golongan_barang,
status_tingkat, status_beton,
sub_skpd, skpd, lokasi_bidang, kabupaten, provinsi, view_tanah_tanpa_harga_kabupaten
WHERE
1 = 1 AND
harga_gedung_bangunan.id_gedung_bangunan = gedung_bangunan.id AND
harga_gedung_bangunan.id_asal_usul = asal_usul.id AND
harga_gedung_bangunan.tahun <= 2021 AND
gedung_bangunan.id_kode_barang_108 = kode_barang_108.id AND
gedung_bangunan.id_mutasi_berkurang = mutasi_berkurang.id AND
gedung_bangunan.id_keadaan_barang = keadaan_barang.id AND
gedung_bangunan.id_satuan_barang = satuan_barang.id AND
gedung_bangunan.id_golongan_barang = golongan_barang.id AND
golongan_barang.id = 3 AND
gedung_bangunan.id_status_tingkat = status_tingkat.id AND
gedung_bangunan.id_status_beton = status_beton.id AND
gedung_bangunan.id_tanah = view_tanah_tanpa_harga_kabupaten.id_tanah AND
gedung_bangunan.id_sub_skpd = sub_skpd.id AND
sub_skpd.id_skpd = skpd.id AND
skpd.id_lokasi_bidang = lokasi_bidang.id AND
lokasi_bidang.id_kabupaten = kabupaten.id AND
kabupaten.id_provinsi = provinsi.id
GROUP BY
gedung_bangunan.id_sub_skpd,
sub_skpd.nama_sub_skpd,
sub_skpd.id_skpd,
skpd.nama_skpd,
skpd.id_lokasi_bidang,
lokasi_bidang.nama_lokasi_bidang,
lokasi_bidang.id_kabupaten,
kabupaten.nama_kabupaten,
kabupaten.id_provinsi,
provinsi.nama_provinsi,
gedung_bangunan.id_mutasi_berkurang,
mutasi_berkurang.mutasi_berkurang,
keadaan_barang.keadaan_barang,
satuan_barang.satuan_barang,
golongan_barang.golongan_barang,
gedung_bangunan.id_golongan_barang,
gedung_bangunan.nama_barang,
kode_barang_108,
kode_l2,
register,
merk_type,
no_no,
bahan,
harga_gedung_bangunan.tahun,
gedung_bangunan.keterangan) AS QUERY_GEDUNG_BANGUNAN
;
GRANT ALL PRIVILEGES ON view_penyusutan_108_gb_2021_r2_a1 TO user_laporan;
REVOKE INSERT, UPDATE, DELETE ON view_penyusutan_108_gb_2021_r2_a1 FROM user_laporan;
Ini adalah algoritma pertama, yaitu penggabungan table-table dasar menjadi query laporan kartu inventaris barang (KIB) C Gedung dan Bangunan.
Beberapa bagian query saya jelaskan sebagai berikut:
DROP VIEW IF EXISTS view_penyusutan_108_gb_2021_r2_a1 CASCADE;
Perintah ini agar mudah melakukan reload sebuah view, baik ketika view itu telah ada, atau pun belum ada. Kalau view sudah ada, maka view tersebut di delete dulu, baru di buat view baru dengan nama yang sama.
LEFT(kode_barang_108.kode_barang_108, 18) kode_barang_108,
Perintah Left, mengambil 18 buah karakter dari kode barang Permendagri 108 agar masuk ke kolom kode_barang_108.
harga_gedung_bangunan.tahun,
Tahun disini adalah tahun pada table harga_gedung_bangunan.
CONCAT(SUM(harga_gedung_bangunan.luas_lantai), ' m2') as ukuran_barang,
Setiap rehab aset tetap, kalau ada yang menambah luas lantai, maka luas lantai keseluruhan adalah total luas lantai.
SUM(harga_gedung_bangunan.harga_bertambah) - SUM(harga_gedung_bangunan.harga_berkurang) harga,
Perhitungan ini berguna agar kalau ada koreksi berkurang terhadap aset tetap, bisa di input ke kolom harga_berkurang, sehingga total harga nya akan mengikuti sesuai data entry nya.
harga_gedung_bangunan.tahun <= 2021 AND
Pembatasan ini, agar perhitungan hanya memasukkan semua pengadaan sampai dengan tahun 2021.
golongan_barang.id = 3 AND
Filter golongan barang hanya gedung dan bangunan, karena dalam table gedung_bangunan, terdapat pula golongan Konstruksi dalam Pengerjaan.
GRANT ALL PRIVILEGES ON view_penyusutan_108_gb_2021_r2_a1 TO user_laporan;
REVOKE INSERT, UPDATE, DELETE ON view_penyusutan_108_gb_2021_r2_a1 FROM user_laporan;
Berikan hak akses kepada user user_laporan, dan cabut akses user_laporan untuk melakukan INSERT. UPDATE dan DELETE data di dalam database.
Kedua
DROP view if exists view_penyusutan_108_gb_2021_r2_e2 CASCADE;
create view view_penyusutan_108_gb_2021_r2_e2 as select
nama_skpd,
id_skpd,
nama_lokasi_bidang,
id_lokasi_bidang,
nama_kabupaten,
id_kabupaten,
nama_provinsi,
id_provinsi,
id_mutasi_berkurang,
mutasi_berkurang,
keadaan_barang,
nama_barang,
register,
harga,
sum (harga) over (partition by register order by tahun asc) as nilai_perolehan,
tahun,
view_penyusutan_108_gb_2021_r2_a1.kode_barang_108,
left(view_penyusutan_108_gb_2021_r2_a1.kode_barang_108, 11) as kode_umur,
rank() over (partition by register order by tahun asc) as rank,
lead(tahun, 1, 2022) over (partition by register order by tahun asc) as tahun_akhir,
umur as masa_manfaat,
0 as penambahan_umur,
umur as umur_awal,
CASE WHEN ((lead(tahun, 1, 2022) over (partition by register order by tahun asc)) - tahun) < umur
THEN umur - ((lead(tahun, 1, 2022) over (partition by register order by tahun asc)) - tahun)
ELSE
0
END as sisa_umur,
harga as nilai_buku_awal,
CASE WHEN ((lead(tahun, 1, 2022) over (partition by register order by tahun asc)) - tahun) < umur
THEN round(((lead(tahun, 1, 2022) over (partition by register order by tahun asc)) - tahun) * harga / umur, 0)
ELSE
harga
END as penyusutan,
CASE WHEN ((lead(tahun, 1, 2022) over (partition by register order by tahun asc)) - tahun) < umur
THEN harga - (round(((lead(tahun, 1, 2022) over (partition by register order by tahun asc)) - tahun) * harga / umur, 0))
ELSE
0
END as nilai_buku_akhir
from view_penyusutan_108_gb_2021_r2_a1, kode_barang_108
where view_penyusutan_108_gb_2021_r2_a1.kode_barang_108 = left(kode_barang_108.kode_barang_108, 18)
order by register, rank;
Cek umur barang, apakah lebih dari umur ekonomis. Bila lebih, berarti disusutkan seluruh nilainya.
Ketiga
DROP view if exists view_penyusutan_108_gb_2021_r2_e3 CASCADE;
create view view_penyusutan_108_gb_2021_r2_e3 as
select register,
nama_skpd,
id_skpd,
nama_lokasi_bidang,
id_lokasi_bidang,
nama_kabupaten,
id_kabupaten,
nama_provinsi,
id_provinsi,
id_mutasi_berkurang,
mutasi_berkurang,
keadaan_barang,
nama_barang,
harga,
nilai_perolehan,
tahun,
view_penyusutan_108_gb_2021_r2_e2.kode_barang_108,
kode_umur,
rank,
tahun_akhir,
CASE WHEN rank > 1 AND lag(nilai_perolehan) over urutan > 0
THEN round (100 * (harga / lag(nilai_perolehan) over urutan),2)
WHEN rank > 1 AND lag(nilai_perolehan) over urutan <= 0
THEN round(100,2)
WHEN rank = 1
THEN 0
ELSE
0
END as persen_awal,
CASE WHEN
CASE WHEN rank > 1 AND lag(nilai_perolehan) over urutan > 0
THEN round (100 * (harga / lag(nilai_perolehan) over urutan),2)
WHEN rank > 1 AND lag(nilai_perolehan) over urutan <= 0
THEN round(100,2)
WHEN rank = 1
THEN 0
ELSE
0
END
> 75
THEN 100
WHEN
CASE WHEN rank > 1 AND lag(nilai_perolehan) over urutan > 0
THEN round (100 * (harga / lag(nilai_perolehan) over urutan),2)
WHEN rank > 1 AND lag(nilai_perolehan) over urutan <= 0
THEN round(100,2)
WHEN rank = 1
THEN 0
ELSE
0
END
> 50
THEN 75
WHEN
CASE WHEN rank > 1 AND lag(nilai_perolehan) over urutan > 0
THEN round (100 * (harga / lag(nilai_perolehan) over urutan),2)
WHEN rank > 1 AND lag(nilai_perolehan) over urutan <= 0
THEN round(100,2)
WHEN rank = 1
THEN 0
ELSE
0
END
> 25
THEN 50
WHEN
CASE WHEN rank > 1 AND lag(nilai_perolehan) over urutan > 0
THEN round (100 * (harga / lag(nilai_perolehan) over urutan),2)
WHEN rank > 1 AND lag(nilai_perolehan) over urutan <= 0
THEN round(100,2)
WHEN rank = 1
THEN 0
ELSE
0
END
> 0
THEN 25
ELSE
0
END as persentasi,
masa_manfaat,
penambahan_umur,
umur_awal,
sisa_umur,
nilai_buku_awal,
penyusutan,
nilai_buku_akhir
from
view_penyusutan_108_gb_2021_r2_e2
Window
urutan as (partition by register order by rank)
order by register, rank;
Mengubah persen_awal menjadi persen yang dapat di link ke table penambahan_umur.
Adapun sisa_umur_temp di buat untuk mengakses sisa_umur pada baris sebelumnya.
Akses penambahan_umur, terdapat bug pada query sql, yaitu ketika link ke table penambahan_umur, maka tidak dilakukan link seperti biasa, yaitu
persentasi = view_penambahan_umur_108.persen
tetapi
view_penambahan_umur_108.persen > 75
Saya tidak tahu kenapa seperti itu.
Keempat
DROP view if exists view_penyusutan_108_gb_2021_r2_e4 CASCADE;
create view view_penyusutan_108_gb_2021_r2_e4 as
select register,
nama_skpd,
id_skpd,
nama_lokasi_bidang,
id_lokasi_bidang,
nama_kabupaten,
id_kabupaten,
nama_provinsi,
id_provinsi,
id_mutasi_berkurang,
mutasi_berkurang,
keadaan_barang,
nama_barang,
harga,
nilai_perolehan,
tahun,
view_penyusutan_108_gb_2021_r2_e3.kode_barang_108,
kode_umur,
rank,
tahun_akhir,
persen_awal,
persentasi,
masa_manfaat,
CASE WHEN rank > 1
THEN view_penambahan_umur_108.umur
WHEN rank = 1
THEN 0
ELSE
0
END as penambahan_umur,
umur_awal,
sisa_umur,
nilai_buku_awal,
penyusutan,
nilai_buku_akhir
from
view_penyusutan_108_gb_2021_r2_e3, view_penambahan_umur_108
where
view_penyusutan_108_gb_2021_r2_e3.kode_umur = view_penambahan_umur_108.kode_kelompok_barang AND
view_penyusutan_108_gb_2021_r2_e3.persentasi = view_penambahan_umur_108.persen
order by register, rank;
Kelima
DROP view if exists view_penyusutan_108_gb_2021_r2_e5 CASCADE;
create view view_penyusutan_108_gb_2021_r2_e5 as
select register,
nama_skpd,
id_skpd,
nama_lokasi_bidang,
id_lokasi_bidang,
nama_kabupaten,
id_kabupaten,
nama_provinsi,
id_provinsi,
id_mutasi_berkurang,
mutasi_berkurang,
keadaan_barang,
nama_barang,
harga,
nilai_perolehan,
tahun,
kode_barang_108,
kode_umur,
rank,
tahun_akhir,
persen_awal,
persentasi,
masa_manfaat,
penambahan_umur,
CASE WHEN rank > 1 AND lag(sisa_umur,1,0) over urutan + penambahan_umur >= masa_manfaat
THEN masa_manfaat
WHEN rank = 1
THEN masa_manfaat
ELSE
lag(sisa_umur,1,0) over urutan + penambahan_umur
END as umur_awal,
CASE WHEN rank > 1 AND lag(sisa_umur,1,0) over urutan + penambahan_umur - (tahun_akhir - tahun) > 0
AND lag(sisa_umur,1,0) over urutan + penambahan_umur - (tahun_akhir - tahun) <= masa_manfaat
THEN lag(sisa_umur,1,0) over urutan + penambahan_umur - (tahun_akhir - tahun)
WHEN rank > 1 AND lag(sisa_umur,1,0) over urutan + penambahan_umur - (tahun_akhir - tahun) > 0
AND lag(sisa_umur,1,0) over urutan + penambahan_umur - (tahun_akhir - tahun) > masa_manfaat
AND masa_manfaat - (tahun_akhir - tahun) > 0
THEN masa_manfaat - (tahun_akhir - tahun)
WHEN rank = 1 AND masa_manfaat - (tahun_akhir - tahun) > 0
THEN masa_manfaat - (tahun_akhir - tahun)
ELSE
0
END as sisa_umur,
COALESCE(lag(nilai_buku_akhir) over urutan, 0) + harga as nilai_buku_awal,
CASE WHEN (tahun_akhir - tahun) <
CASE WHEN rank > 1 AND lag(sisa_umur,1,0) over urutan + penambahan_umur >= masa_manfaat
THEN masa_manfaat
WHEN rank = 1
THEN masa_manfaat
ELSE
lag(sisa_umur,1,0) over urutan + penambahan_umur
END
THEN round((tahun_akhir - tahun) * (COALESCE(lag(nilai_buku_akhir) over urutan, 0) + harga) /
(CASE WHEN rank > 1 AND lag(sisa_umur,1,0) over urutan + penambahan_umur >= masa_manfaat
THEN masa_manfaat
WHEN rank = 1
THEN masa_manfaat
ELSE
lag(sisa_umur,1,0) over urutan + penambahan_umur
END),
0)
ELSE
COALESCE(lag(nilai_buku_akhir) over urutan, 0) + harga
END as penyusutan,
CASE WHEN (tahun_akhir - tahun) <
CASE WHEN rank > 1 AND lag(sisa_umur,1,0) over urutan + penambahan_umur >= masa_manfaat
THEN masa_manfaat
WHEN rank = 1
THEN masa_manfaat
ELSE
lag(sisa_umur,1,0) over urutan + penambahan_umur
END
THEN (COALESCE(lag(nilai_buku_akhir) over urutan, 0) + harga) -
(round((tahun_akhir - tahun) * (COALESCE(lag(nilai_buku_akhir) over urutan, 0) + harga) /
(CASE WHEN rank > 1 AND lag(sisa_umur,1,0) over urutan + penambahan_umur >= masa_manfaat
THEN masa_manfaat
WHEN rank = 1
THEN masa_manfaat
ELSE
lag(sisa_umur,1,0) over urutan + penambahan_umur
END),
0))
ELSE
(COALESCE(lag(nilai_buku_akhir) over urutan, 0) + harga) - (COALESCE(lag(nilai_buku_akhir) over urutan, 0) + harga)
END as nilai_buku_akhir
from
view_penyusutan_108_gb_2021_r2_e4
Window
urutan as (partition by register order by rank)
order by register, rank;
Algoritma Ketiga, Keempat dan Kelima harus di ulang sejumlah baris data tahun penambahan umur. Saya tidak tahu kenapa seperti itu, adapun kalau tidak di ulang, maka angka yang dihasilkan tidak tepat. Ini adalah bug dalam algoritma ini.
Keenam
DROP view if exists view_penyusutan_108_gb_2021_r2_a3 CASCADE;
create view view_penyusutan_108_gb_2021_r2_a3 as
select register,
nama_skpd,
id_skpd,
nama_lokasi_bidang,
id_lokasi_bidang,
nama_kabupaten,
id_kabupaten,
nama_provinsi,
id_provinsi,
id_mutasi_berkurang,
mutasi_berkurang,
keadaan_barang,
nama_barang,
harga,
nilai_perolehan,
sum(harga) over (partition by register) as harga_total,
tahun,
kode_barang_108,
kode_umur,
rank,
tahun_akhir - 1 as tahun_akhir,
persen_awal,
persentasi,
masa_manfaat,
penambahan_umur,
umur_awal,
sisa_umur,
nilai_buku_awal,
penyusutan,
nilai_buku_akhir
from
view_penyusutan_108_gb_2021_r2_e29
order by register, rank;
GRANT ALL PRIVILEGES ON view_penyusutan_108_gb_2021_r2_a3 TO user_laporan;
REVOKE INSERT, UPDATE, DELETE ON view_penyusutan_108_gb_2021_r2_a3 FROM user_laporan;
Ketujuh
DROP view if exists view_penyusutan_108_gb_2021_r2_a4 CASCADE;
create view view_penyusutan_108_gb_2021_r2_a4 as
select register,
nama_skpd,
id_skpd,
nama_lokasi_bidang,
id_lokasi_bidang,
nama_kabupaten,
id_kabupaten,
nama_provinsi,
id_provinsi,
id_mutasi_berkurang,
mutasi_berkurang,
keadaan_barang,
nama_barang,
kode_barang_108,
min(tahun) as tahun_awal,
sum(harga) as nilai_perolehan,
sum(penyusutan) as penyusutan,
sum(harga) - sum(penyusutan) as nilai_buku
from
view_penyusutan_108_gb_2021_r2_a3
GROUP BY
register,
nama_skpd,
id_skpd,
nama_lokasi_bidang,
id_lokasi_bidang,
nama_kabupaten,
id_kabupaten,
nama_provinsi,
id_provinsi,
id_mutasi_berkurang,
mutasi_berkurang,
keadaan_barang,
nama_barang,
kode_barang_108
order by register;
GRANT ALL PRIVILEGES ON view_penyusutan_108_gb_2021_r2_a4 TO user_laporan;
REVOKE INSERT, UPDATE, DELETE ON view_penyusutan_108_gb_2021_r2_a4 FROM user_laporan;
Kedelapan
DROP view if exists view_beban_penyusutan_108_gb_2021_r2_a1 CASCADE;
create view view_beban_penyusutan_108_gb_2021_r2_a1 as
select register,
nama_skpd,
id_skpd,
nama_lokasi_bidang,
id_lokasi_bidang,
nama_kabupaten,
id_kabupaten,
nama_provinsi,
id_provinsi,
id_mutasi_berkurang,
mutasi_berkurang,
keadaan_barang,
nama_barang,
kode_barang_108,
tahun_awal,
nilai_perolehan as nilai_perolehan_sd_2020,
0 as nilai_perolehan_sd_2021,
nilai_buku as nilai_buku_sd_2020,
0 as nilai_buku_sd_2021
from
view_penyusutan_108_gb_2020_r2_a4
UNION ALL
select register,
nama_skpd,
id_skpd,
nama_lokasi_bidang,
id_lokasi_bidang,
nama_kabupaten,
id_kabupaten,
nama_provinsi,
id_provinsi,
id_mutasi_berkurang,
mutasi_berkurang,
keadaan_barang,
nama_barang,
kode_barang_108,
tahun_awal,
0 as nilai_perolehan_sd_2020,
nilai_perolehan as nilai_perolehan_sd_2021,
0 as nilai_buku_sd_2020,
nilai_buku as nilai_buku_sd_2021
from
view_penyusutan_108_gb_2021_r2_a4
order by register;
Kesembilan
DROP view if exists view_beban_penyusutan_108_gb_2021_r2_a2 CASCADE;
create view view_beban_penyusutan_108_gb_2021_r2_a2 as
select register,
nama_skpd,
id_skpd,
nama_lokasi_bidang,
id_lokasi_bidang,
nama_kabupaten,
id_kabupaten,
nama_provinsi,
id_provinsi,
id_mutasi_berkurang,
mutasi_berkurang,
keadaan_barang,
nama_barang,
kode_barang_108,
min(tahun_awal) as tahun_awal,
sum(nilai_perolehan_sd_2020) as nilai_perolehan_sd_2020,
sum(nilai_perolehan_sd_2021) - sum(nilai_perolehan_sd_2020) as penambahan_nilai_di_2021,
sum(nilai_perolehan_sd_2021) as nilai_perolehan_sd_2021,
sum(nilai_perolehan_sd_2020) - sum(nilai_buku_sd_2020) as nilai_penyusutan_sd_2020,
sum(nilai_buku_sd_2020) as nilai_buku_sd_2020,
sum(nilai_buku_sd_2020) +
(sum(nilai_perolehan_sd_2021) - sum(nilai_perolehan_sd_2020)) -
sum(nilai_buku_sd_2021) as beban_penyusutan_2021,
sum(nilai_perolehan_sd_2021) - sum(nilai_buku_sd_2021) as nilai_penyusutan_sd_2021,
sum(nilai_buku_sd_2021) as nilai_buku_sd_2021
from
view_beban_penyusutan_108_gb_2021_r2_a1
GROUP BY
register,
nama_skpd,
id_skpd,
nama_lokasi_bidang,
id_lokasi_bidang,
nama_kabupaten,
id_kabupaten,
nama_provinsi,
id_provinsi,
id_mutasi_berkurang,
mutasi_berkurang,
keadaan_barang,
nama_barang,
kode_barang_108
order by register;
GRANT ALL PRIVILEGES ON view_beban_penyusutan_108_gb_2021_r2_a2 TO user_laporan;
REVOKE INSERT, UPDATE, DELETE ON view_beban_penyusutan_108_gb_2021_r2_a2 FROM user_laporan;
Sekian tulisan ini, semoga bermanfaat.