Aplikasi Inventory Sederhana

Aplikasi Inventory Sederhana menggunakan VB VBnet MySQL

Membuat Aplikasi Inventory Sederhana atau Aplikasi Stok Barang adalah salah satu topik yang sangat umum, dan sering dijadikan sebagai salah satu topik skripsi, atau sekedar untuk mempelajari bahasa pemrograman tertentu. Aplikasi inventory juga menjadi topik yang cukup digemari karena kemungkinan pengguna yang sangat banyak, mulai dari warung-warung pinggir jalan sampai dengan hipermarket akan memerlukan aplikasi inventory untuk mengontrol status barang yang mereka jual. Bagi seorang programmer pemula, membuat aplikasi inventory juga bisa menjadi batu loncatan untuk membangun aplikasi perkantoran yang jauh lebih rumit.

Untuk itu saya akan mencoba membuat sebuah Tutorial Membuat Aplikasi Inventory Sederhana Menggunakan VB.net dan Database MySQL. VB.net dipilih karena merupakan salah satu bahasa yang sangat populer di Indonesia, dan sama halnya dengan database MySQL. Tutorial ini akan dibuat berseri menjadi artikel-artikel kecil untuk memudahkan teman-teman mempelajari konsep yang ada di dalamnya.

Struktur dari tutorial ini akn dibagi-bagi menjadi subtopik kecil adalah sebagai berikut:

  1. Analisa dan Desain Aplikasi. Menjabarkan hasil analisa dan desain untuk aplikasi yang akan dibuat. Untuk memudahkan, Diagram UML Use Case akan digunakan untuk menggambarkan fitur-fitur yang akan tersedia dalam Aplikasi Inventory Sederhana ini.
  2. Analisa dan Desain Database. Menjabarkan hasil analisa dan desain database yang akan digunakan untuk menyimpan data barang dan transaksinya. Notasi IDEF1X akan digunakan untuk diagram desain database-nya
  3. Penggunaan Trigger untuk Update Stok Barang. Menjabarkan desain database trigger untuk melakukan proses update saldo stok barang setiap kali ada transaksi barang masuk dan transaksi barang keluar. Artikel ini dilengkapi dengan test langkah-demi-langkah untuk mempermudah pemahaman materi.
  4. Desain User Interface. Menjabarkan desain umum user interface dan pemanfaatan visual inheritance untuk mendapatkan tampilan yang konsisten untuk semua form dalam aplikasi ini.
  5. Desain Data Access Layer. Menjabarkan desain lapisan data akses untuk mempermudah kita membuat aplikasi ini. Untuk Data Access Layer ini akan kita gunakan ADO.net 2.0 terlebih dahulu untuk mempermudah teman-teman dalam migrasi dari VB6 ke VB.net. Kalau ada kesempatan nanti kita bisa buat menggunakan Entity Framework.
  6. Membuat Form Master Barang. Menjabarkan detil langkah demi langkah membuat form master barang, mencakup keseluruhan fungsi CRUD (Created Read Update Delete) untuk data barang.
  7. Membuat Form Transaksi Barang Masuk. Menjabarkan detil langkah demi langkah membuat form transaksi barang masuk, mencakup keseluruhan fungsi CRUD (Created Read Update Delete) untuk data transaksi barang masuk.
  8. Membuat Form Transaksi Barang Keluar. Menjabarkan detil langkah demi langkah membuat form transaksi barang keluar, mencakup keseluruhan fungsi CRUD (Created Read Update Delete) untuk transaksi barang keluar.
  9. Membuat Form Laporan Kartu Stok, Menjabarkan pembuatan form yang menampilkan data kartu stok masing-masing barang, meliputi kronologis keluar masuknya barang.
  10. Membuat Form Laporan Mutasi Stok, Menjabarkan pembuatan form yang menampilkan data kartu stok keseluruhan barang, berupa summary barang masuk dan keluar serta saldo terakhir barang tercatat di gudang.

 

Jadi….. Bookmark segera artikel ini, karena artikel-artikel lanjutan akan diterbitkan secara periodik. Dan mudah-mudahan tutorial ini dapat membantu teman-teman mempelajari VB.net.

Semangat Belajar!

^_^

Belajar SQL: CASE Clause – Logika Percabangan

Belajar SQL Logika Percabangan Case clause

Belajar SQL Logika Percabangan Case clauseSalah satu fungsi atau clause yang kurang begitu populer di SQL adalah CASE clause. Salah satu sebabnya adalah umunya SQL lebih dikenal hanya untuk proses SELECT, INSERT, UPDATE dan DELETE saja, dan karena CASE clause punya fungsi yang sama dengan IF di semua bahasa pemrograman yang ada, misalkan PHP, Java, dan sebagainya. Untuk itu saya akan berikan contoh sederhana penggunaan SQL untuk melakukan perhitungan dengan sedikit logika IF sederhana.

Misalkan kita mempunya contoh data seperti berikut ini

mysql> select * from penggunaan;
+----------+-------+--------+-------+-------+-------+-------+--------+
| kegiatan | senin | selasa | rabu  | kamis | jumat | sabtu | minggu |
+----------+-------+--------+-------+-------+-------+-------+--------+
| olahraga | ya    | tidak  | ya    | tidak | ya    | tidak | tidak  |
| diskusi  | tidak | ya     | tidak | tidak | tidak | ya    | tidak  |
| rapat    | ya    | tidak  | tidak | tidak | tidak | tidak | tidak  |
| ulangan  | tidak | ya     | ya    | ya    | tidak | tidak | tidak  |
+----------+-------+--------+-------+-------+-------+-------+--------+
4 rows in set (0.00 sec)

ketika kita ingin tahu berapa banyak dalam seminggu kegiatan-kegiatan tersebut di atas dilakukan atau tidak. Sebagai contoh untuk kegiatan OLAHRAGA dalam satu minggu dilakukan sebanyak 3 kali dan tidak dilakukan sebanyak 4 kali. jika kita bisa dengan mudah menggunakan PHP dan looping untuk menghitungnya menggunakan logika percabangan IF, misalkan.

if ($row['senin']=='ya')
    $dilakukan += 1;
else
    $tidak_dilakukan += 1;

Kalau menggunakan SQL caranya adalah seperti ini

mysql> select penggunaan.*
    -> , case when senin='ya' then 1 else 0 end
    -> + case when selasa='ya' then 1 else 0 end
    -> + case when rabu='ya' then 1 else 0 end
    -> + case when kamis='ya' then 1 else 0 end
    -> + case when jumat='ya' then 1 else 0 end
    -> + case when sabtu='ya' then 1 else 0 end
    -> + case when minggu='ya' then 1 else 0 end as dilakukan
    -> , case when senin='tidak' then 1 else 0 end
    -> + case when selasa='tidak' then 1 else 0 end
    -> + case when rabu='tidak' then 1 else 0 end
    -> + case when kamis='tidak' then 1 else 0 end
    -> + case when jumat='tidak' then 1 else 0 end
    -> + case when sabtu='tidak' then 1 else 0 end
    -> + case when minggu='tidak' then 1 else 0 end as tidak_dilakukan
    -> from penggunaan ;

Saat menghitung jumlah "dilakukan" kita berikan nilai 1 jika field berisikan 'ya', selain itu beli nilai 0. Dan saat menghitung jumlah "tidak_dilakukan" kita berikan nilai 1 jika field berisikan 'tidak', selain itu beli nilai 0. Setelah itu jumlahkan semua CASE clause tersebut sehingga kita dapatkan hasil seperti ini

+----------+-------+--------+-------+-------+-------+-------+--------+-----------+-----------------+
| kegiatan | senin | selasa | rabu  | kamis | jumat | sabtu | minggu | dilakukan | tidak_dilakukan |
+----------+-------+--------+-------+-------+-------+-------+--------+-----------+-----------------+
| olahraga | ya    | tidak  | ya    | tidak | ya    | tidak | tidak  |         3 |               4 |
| diskusi  | tidak | ya     | tidak | tidak | tidak | ya    | tidak  |         2 |               5 |
| rapat    | ya    | tidak  | tidak | tidak | tidak | tidak | tidak  |         1 |               6 |
| ulangan  | tidak | ya     | ya    | ya    | tidak | tidak | tidak  |         3 |               4 |
+----------+-------+--------+-------+-------+-------+-------+--------+-----------+-----------------+
4 rows in set (0.00 sec)

Tadaaaa….. Bagaimana? Luar biasa, bukan?

Dengan satu perintah SQL, kita bisa mendapatkan data yang matang dan ketika membuat program PHP-nya kita cukup menmpilkannya saja dalam bertuk <table></table> dan tidak perlu menghitung-hitung lagi. Mudah dan Cepat (y)

Login Page Sederhana

login form sederhana

login form sederhanaSalah satu topik yang cukup menantang bagi programmer pemula ada membuat login page atau halaman login sederhana. Menantang bagi programmer pemula karena banyak hal yang harus dipahami sebelum bisa membuat sebuah login page atau halaman login bisa bekerja dengan benar. Form login ini menjadi penting karena kemampuan meracik form login akan sangat membantu membuat aplikasi web yang membutuhkan hak akses dalam penggunaannya. Misalkan aplikasi perkantoran, aplikasi perpustakaan, akses halaman admin. dan sebagainya.

(more…)

The Magic of Trigger

database trigger after insert mysql

database trigger after insert mysqlSalah satu business rule yang banyak dijumpai dalam aplikasi perkantoran adalah penyimpana data menggunakan skema table master-detail seperti data Purchase Order, Invoice dan sebagainya. Tantangannya adalah membuat sebuah field yang berisi summary nilai pembelian yang ada di dalam table detail. Misalkan ada data Purchase Order dengan 5 item masing-masing bernilai 1.000.000 rupiah maka akan ada field summary di table master yang berisikan nilai 5.000.000.

Business Rule seperti di atas dapat di-enforce di level aplikasi menggunakan code PHP, Java, atau .net. Namun dapat juga dilakukan di level database dengan menggunakan trigger. Untuk mencapainya silakan ikuti langkah-langkah berikut ini,

Pertama-tama kita buat table master dan table detail.

mysql> -----------------------------
mysql> -- buat table header
mysql> -----------------------------
mysql> create table header (
    ->   id int auto_increment primary key,
    ->   amount int default 0
    -> ) ;
Query OK, 0 rows affected (0.04 sec)
 
mysql> -----------------------------
mysql> -- buat table detail
mysql> -----------------------------
mysql> create table detail (
    ->   id int auto_increment primary key,
    ->   header_id int not null,
    ->   quantity int default 0,
    ->   unit_price int default 0,
    ->   foreign key (header_id) references header (id)
    -> ) ;
Query OK, 0 rows affected (0.03 sec)

Kemudian coba kita buatkan trigger untuk meng-handle aktifitas insert ke table detail. Logikanya adalah, setiap kali ada penginputan row baru ke table detail maka field amount di table master harus diubah.

mysql> -----------------------------
mysql> -- buat insert trigger untu tabel detail
mysql> -- amount di table header dihitung
mysql> -- berdasarkan perkalian quantity*unit_price
mysql> -----------------------------
mysql> delimiter |
mysql> create trigger trg_detail_insert
    -> after insert on detail
    -> for each row
    -> begin
    ->   update header
    ->   set amount = (
    ->     select sum(quantity*unit_price)
    ->     from detail where header_id = new.header_id )
    ->   where id = new.header_id ;
    -> end;
    -> |
Query OK, 0 rows affected (0.01 sec)
 
mysql> delimiter ; 

Untuk keperluan ujicoba, maka kita masukkan beberapa row record ke table master dan coba tampilkan untuk mengetahui isinya. Dan dapat terlihat bahwa amount masih bernilai 0 (nol)

mysql> -----------------------------
mysql> -- insert sampel data ke header
mysql> -- kemudian tampilkan
mysql> -----------------------------
mysql> insert into header(amount)
    -> values (0), (0), (0) ;
Query OK, 3 rows affected (0.02 sec)
Records: 3  Duplicates: 0  Warnings: 0
 
mysql> select * from header ;
+----+--------+
| id | amount |
+----+--------+
|  1 |      0 |
|  2 |      0 |
|  3 |      0 |
+----+--------+
3 rows in set (0.00 sec)
Kemudian coba kita masukkan beberapa row record data ke table detail dan coba tampilkan isinya.
mysql> -----------------------------
mysql> -- insert sampel data ke detail
mysql> -- kemudian tampilkan
mysql> -----------------------------
mysql> insert into detail (header_id, quantity, unit_price)
    -> values (1, 10, 100), (1, 2, 300),
    ->        (2, 1, 500), (2, 5, 300) ;
Query OK, 4 rows affected (0.04 sec)
Records: 4  Duplicates: 0  Warnings: 0
 
mysql> select * from detail;
+----+-----------+----------+------------+
| id | header_id | quantity | unit_price |
+----+-----------+----------+------------+
|  3 |         1 |       10 |        100 |
|  4 |         1 |        2 |        300 |
|  5 |         2 |        1 |        500 |
|  6 |         2 |        5 |        300 |
+----+-----------+----------+------------+
4 rows in set (0.00 sec)

Setelah kita lihat data yang ada di table detail di atas, maka seharusnya trigger akan mengubah field amount yang ada di table master. jadi sekarang kita coba tampilkan isi table master seperti di bawah ini.

mysql> -----------------------------
mysql> -- coba tampilkan isi table header
mysql> -- seharusnya amount sudah berubah
mysql> -----------------------------
mysql> select * from header;
+----+--------+
| id | amount |
+----+--------+
|  1 |   1600 |
|  2 |   2000 |
|  3 |      0 |
+----+--------+
3 rows in set (0.00 sec)

Tadaaa……. Sukses…. BERHASIL !!!!

mysql> -----------------------------
mysql> -- YESS....... !!!
mysql> -- it works
mysql> -----------------------------
mysql>

Setelah ini masih ada beberapa hal yang dapat dikembangkan lagi, yaitu trigger untuk proses UPDATE detail, karena proses update di table detail seharusnya juga mengubah nilai amount yang ada di table master. Selain itu contoh di atas menggunakan database MySQL, sehingga teman-teman yang ingin menerapkannya di sistem RDBMS lain harus menyesuaikan kembali sintaks-nya.

Semoga tutorial ini bisa bermanfaat.

Dynamic CrossTab di MySQL

Membuat report adalah salah satu pekerjaan yang cukup rumit, lebih lagi jika harus membuat report crosstab dengan jumlah kolom yang dinamis dijamin pusing tujuh keliling. Laporan crosstab ini adalah laporan yang mengolah data mentah berupa baris-baris menjadi kolom-kolom.

Mencoba menjawab sejumlah pertanyaan tentang crosstab dinamis yang muncul di Facebook grup PHP Indonesia dan MySQL Indonesia, akhirnya saya penasaran juga….

Misalkan kita punya data transaksi seperti tabel di bawah ini:

+-------+------------+-------+
| kode  | tanggal    | nilai |
+-------+------------+-------+
| CN235 | 2012-01-02 |   100 |
| CN235 | 2012-01-11 |   140 |
| CN235 | 2012-01-11 |   150 |
| CN235 | 2012-01-15 |   160 |
| CN235 | 2012-01-17 |   180 |
| CN235 | 2012-01-17 |   170 |
| CN236 | 2012-01-02 |   800 |
| CN236 | 2012-01-11 |   200 |
| CN236 | 2012-01-11 |   400 |
| CN236 | 2012-01-15 |   120 |
| CN236 | 2012-01-17 |   400 |
| N2130 | 2012-01-02 |   120 |
| N2130 | 2012-01-15 |   200 |
| N2130 | 2012-01-17 |   600 |
+-------+------------+-------+

Namun kita perlu membuat laporan seperti ini

+-------+------------+------------+------------+------------+-------+
| kode  | 2012-01-02 | 2012-01-11 | 2012-01-15 | 2012-01-17 | total |
+-------+------------+------------+------------+------------+-------+
| CN235 |        100 |        290 |        160 |        350 |   900 |
| CN236 |        800 |        600 |        120 |        400 |  1920 |
| N2130 |        120 |          0 |        200 |        600 |   920 |
+-------+------------+------------+------------+------------+-------+

Kolom 2012-01-02 sampai 2012-01-17 sifatnya dinamis, artinya kolom tanggal bisa jadi tidak hanya 4 kolom, bisa lebih banyak, dan bisa juga lebih sedikit, tergantung dari data yang ada.

Solusinya adalah memanfaatkan stored procedure di MySQL, dan aplikasi PHP kita cukup terima data mateng hasil perhitungan stored procedure bersangkutan, dan Alhamdulillah berhasil menemukan solusi seperti di bawah ini. Silakan dipelajari 😀

PS C:\Users\hiday> mysql -u root
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 26
Server version: 10.5.7-MariaDB-log mariadb.org binary distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> use test
Database changed

MariaDB [test]> -- First drop sample table if already exists
MariaDB [test]> DROP TABLE if exists transaksi cascade;
Query OK, 0 rows affected (0.009 sec)

MariaDB [test]> -- Create our test table
MariaDB [test]> CREATE TABLE transaksi as
    ->     select 'CN235' kode, '2012-01-02' tanggal, 100 nilai union all
    ->     select 'N2130' kode, '2012-01-02' tanggal, 120 nilai union all
    ->     select 'CN235' kode, '2012-01-11' tanggal, 140 nilai union all
    ->     select 'CN235' kode, '2012-01-11' tanggal, 150 nilai union all
    ->     select 'CN236' kode, '2012-01-11' tanggal, 200 nilai union all
    ->     select 'CN235' kode, '2012-01-15' tanggal, 160 nilai union all
    ->     select 'CN235' kode, '2012-01-17' tanggal, 170 nilai union all
    ->     select 'CN235' kode, '2012-01-17' tanggal, 180 nilai union all
    ->     select 'N2130' kode, '2012-01-15' tanggal, 200 nilai union all
    ->     select 'CN236' kode, '2012-01-11' tanggal, 400 nilai union all
    ->     select 'CN236' kode, '2012-01-15' tanggal, 120 nilai union all
    ->     select 'CN236' kode, '2012-01-17' tanggal, 400 nilai union all
    ->     select 'N2130' kode, '2012-01-17' tanggal, 600 nilai union all
    ->     select 'CN236' kode, '2012-01-02' tanggal, 800 nilai
    -> ;
Query OK, 14 rows affected (0.018 sec)
Records: 14  Duplicates: 0  Warnings: 0

MariaDB [test]> -- First drop if the procedure already exists
MariaDB [test]> DROP PROCEDURE if exists crosstab_transaksi;
Query OK, 0 rows affected (0.007 sec)

MariaDB [test]> -- Now create our stored procedure
MariaDB [test]> DELIMITER $$
MariaDB [test]> CREATE PROCEDURE crosstab_transaksi()
    -> BEGIN
    ->     -- declare variables
    ->     declare prepsql varchar(1000);
    ->     declare summsql varchar(1000);
    ->     declare totalsql varchar(100);
    ->     -- generate summary clause
    ->     select group_concat(' sum(case when tanggal=\'',tanggal,'\' then nilai else 0 end) as "',tanggal,'"\n')
    ->     into summsql
    ->     from ( select distinct tanggal from transaksi order by tanggal ) tx;
    ->     -- generate full sql query
    ->     set totalsql = ', sum(nilai) as total\n';
    ->     set prepsql = concat('select kode,',summsql,totalsql,'from transaksi group by kode');
    ->     -- executing generated query
    ->     set @mysql = prepsql;
    ->     prepare stmt from @mysql;
    ->     execute stmt;
    ->     -- clean up
    ->     drop prepare stmt;
    -> END$$
Query OK, 0 rows affected (0.007 sec)

MariaDB [test]> DELIMITER ;

MariaDB [test]> -- Let see our sample data
MariaDB [test]> SELECT * from transaksi
    -> ORDER BY kode, tanggal;
+-------+------------+-------+
| kode  | tanggal    | nilai |
+-------+------------+-------+
| CN235 | 2012-01-02 |   100 |
| CN235 | 2012-01-11 |   140 |
| CN235 | 2012-01-11 |   150 |
| CN235 | 2012-01-15 |   160 |
| CN235 | 2012-01-17 |   180 |
| CN235 | 2012-01-17 |   170 |
| CN236 | 2012-01-02 |   800 |
| CN236 | 2012-01-11 |   200 |
| CN236 | 2012-01-11 |   400 |
| CN236 | 2012-01-15 |   120 |
| CN236 | 2012-01-17 |   400 |
| N2130 | 2012-01-02 |   120 |
| N2130 | 2012-01-15 |   200 |
| N2130 | 2012-01-17 |   600 |
+-------+------------+-------+
14 rows in set (0.001 sec)

MariaDB [test]> -- And then call our stored procedure to get the summary
MariaDB [test]> CALL crosstab_transaksi;
+-------+------------+------------+------------+------------+-------+
| kode  | 2012-01-02 | 2012-01-11 | 2012-01-15 | 2012-01-17 | total |
+-------+------------+------------+------------+------------+-------+
| CN235 |        100 |        290 |        160 |        350 |   900 |
| CN236 |        800 |        600 |        120 |        400 |  1920 |
| N2130 |        120 |          0 |        200 |        600 |   920 |
+-------+------------+------------+------------+------------+-------+
3 rows in set (0.001 sec)

Query OK, 1 row affected (0.012 sec)

MariaDB [test]>

Secara umum alur dari stored procedure di atas adalah:

  1. Query ke tabel data untuk mendapatkan kolom crosstab.
  2. Susun sql statement berdasarkan hasil query tersebut
  3. Siapkan sql menggunakan perintah prepare
  4. Jalankan query.

Script yang diperlukan untuk membuat stored procedure nya adalah sebagai berikut,

-- Now create our stored procedure
DELIMITER $$
CREATE PROCEDURE crosstab_transaksi()
BEGIN
    -- declare variables
    declare prepsql varchar(1000);
    declare summsql varchar(1000);
    declare totalsql varchar(100);
    -- generate summary clause
    select group_concat(' sum(case when tanggal=\'',tanggal,'\' then nilai else 0 end) as "',tanggal,'"\n')
    into summsql
    from ( select distinct tanggal from transaksi order by tanggal ) tx;
    -- generate full sql query
    set totalsql = ', sum(nilai) as total\n';
    set prepsql = concat('select kode,',summsql,totalsql,'from transaksi group by kode');
    -- executing generated query
    set @mysql = prepsql;
    prepare stmt from @mysql;
    execute stmt;
    -- clean up
    drop prepare stmt;
END$$
DELIMITER ;

Source code lengkap nya bisa dilihat di sini.

Dengan cara di atas, aplikasi hanya perlu memanggil stored procedure dan langsung mendapatkan hasil report-nya dalam bentuk “matang” tanpa perlu proses perhitungan lagi.

Selamat mencoba… 🙂