
Studi Kasus
Adalah satu hal yang lumrah dalam penerbitan dokumen invoice perusahaan menerapkan kodifikasi penomoran untuk setiap dokumen invoice yang diterbitkan, sebagai contoh: 30912/INV/EXP/III/2010. Hal ini dilakukan untuk mempermudah manajemen dan pengaturan atas dokumen yang dibuat. Permasalahannya adalah bagaimana jika kodifikasi tersebut bersifat dinamis, dalam artian bergantung pada pelanggan-nya, dalam arti misalnya: untuk pelangan PT. DAUN BUAH menggunakan format dokumen 30912/EXP/MAR/2010, sementara untuk PT. SEGARA PERKASA berformat 30912/EXP/03/2010, dan untuk PT. ABADI NUSA menggunakan format 30912/EXP/INV/2010. Hal ini tentunya akan menjadi kasus yang cukup menggelitik untuk dipecahkan.
Pada kasus tersebut, saya memecahkannya dengan membuat rutin khusus untuk menangani kodifikasi yang dinamis tersebut dengan cara melakukan parsing atas format dokumen yang digunakan. Sebagai contoh, dokumen bernomor 30912/EXP/Mar/2010 terdiri atas elemen-elemen berikut: nomor dokumen (30912), bulan (Mar) dan tahun (2010) adapun karakter lainnya dapat dianggap sebagai karakter penyerta (/EXP/).
Secara keseluruhan, format kodifikasi penomoran dokumen pada umumnya melibatkan dua variabel utama, yaitu tanggal, dan nomor dokumen itu sendiri. Atas dua jenis variabel tersebut kemudian kita bisa menyusun elemen-elemen pembentuk atas format nomor dokumen yang akan dibuat, dalam hal ini misalnya: X untuk sebagai nomor dokumen, D untuk tanggal, M untuk bulam, dan Y untuk tahun. Untuk lebih mempermudah pengimplementasian, saya menggunakan aturan yang diterapkan pada bahasa C/C++ untuk memformat tanggal dengan beberapa penambahan fleksibilitas. Sebagai contoh, berikut ini adalah contoh nomor dokumen dan format yang saya implementasikan:
30912/EXP/Mar/2010 = [XXXXX]/EXP/[MMM]/[YYYY]
Elemen bulan dalam hal ini menggunakan metode penamaan pendek (Jan, Feb, Mar, dst), untuk hal tersebut kita menggunakan M sebanyak 3 kali.
00912/INV/III/10 = [XXXXX]/EXP/[M]/[YY]
Elemen bulan dalam hal ini menggunakan metode bilangan romawi, untuk kasus ini saya memanfaatkan elemen M (dikapitalisasi) satu perulangan. begitu pula dengan elemen tahun (Y), dalam hal ini penomoran yang diinginkan adalah menggunakan model dua digit tahun, karenanya kodifikasi disesuaikan dengan menggunakan dua elemen Y.
30912/INV/30/March/2010 = [XXXXX]/INV/[DD]/[MMMM]/[YYYY]
Dalam kasus ini, penomoran dokumen yang diinginkan adalah menggunakan elemen dua digit tanggal karenanya format atas dokumen ini menggunakan dua elemen D. Di sisi lain penomoran tersebut menggunakan nama bulan secara penuh, karenanya format elemen bulan tersebut disesuaikan dengan menggunakan 4 elemen M.
Implementasi
Pemecahan yang paling fleksibel atas kasus di atas adalah dengan memanfaatkan metode parsing atas format dokumen yang ada, parameter input dalam hal ini adalah format dokumen, nomor dokumen, serta tanggal. Proses parsing dilakukan dengan cara memisahkan antara elemen penenomoran serta karakter pembentuk, dalam hal ini untuk membedakan antara elemen dan karakter pembentuk dilakukan dengan mengapit elemen dengan dengan menggunakan karakter yang dianggap paling jarang digunakan, dalam hal ini adalah karakter “[" sebagai pembuka elemen dan karakter "]” sebagai penutup. Atas karakter-karakter yang tidak dianggap sebagai elemen langsung kita salin sebagai output, kemudian saat menemukan elemen yang dikenal maka program akan menghitung berapa jumlah karakter elemen yang digunakan serta jumlah kapitalisasinya kemudian menyisipkan dengan nilai yang sesuai atas elemen tersebut. Berikut adalah implementasi kode serta cara penggunaannya, adapun versi lain yang telah ditingkatkan fleksibilitasnya (namun ditulis dengan menggunakan Python) dapat dilihat di sini.
function FormatNumber(const AFormat: string;
const AValue: integer;
const AYear, APeriod: word): string;
const
APeriodList: array[1..12] of string =
('I','II','III','IV','V','VI',
'VII','VIII','IX','X','XI','XII');
var
BufPos: Integer;
Buffer: array[0..255] of Char;
procedure AppendChars(P: PChar; Count: Integer);
var
N: Integer;
begin
N := SizeOf(Buffer) - BufPos;
if N > Count then N := Count;
if N 0 then Move(P[0], Buffer[BufPos], N);
Inc(BufPos, N);
end;
procedure AppendString(const S: string);
begin
AppendChars(Pointer(S), Length(S));
end;
procedure AppendNumber(Number, Digits: Integer);
const
Format: array[0..3] of Char = '%.*d';
var
NumBuf: array[0..15] of Char;
begin
AppendChars(NumBuf, FormatBuf(NumBuf, SizeOf(NumBuf), Format,
SizeOf(Format), [Digits, Number]));
end;
procedure AppendFormat(AFormat: PChar);
var
Starter, Token: Char;
ACount, ACapital, ATotal: integer;
procedure GetTotal;
var
P: PChar;
begin
P := AFormat;
while AFormat^ = Starter do Inc(AFormat);
ATotal := AFormat - P + 1;
end;
begin
if (AFormat nil) then
begin
ACount := 0;
while AFormat^ #0 do
begin
Starter := AFormat^;
AFormat := StrNextChar(AFormat);
Token := Starter;
if Token in ['a'..'z'] then Dec(Token, 32);
case Token of
'[': Inc(ACount);
']': Dec(ACount);
'X':
begin
if (ACount > 0) then
begin
GetTotal;
AppendNumber(AValue, ATotal)
end else
AppendChars(@Starter, 1);
end;
'M':
begin
if (ACount > 0) then
begin
GetTotal;
if (Starter = Token) then
AppendString(APeriodList[APeriod])
else
begin
case ATotal of
1, 2: AppendNumber(APeriod, ATotal);
3: AppendString(UpperCase(ShortMonthNames[APeriod]));
else
AppendString(UpperCase(LongMonthNames[APeriod]));
end;
end;
end else
AppendChars(@Starter, 1);
end;
'Y':
begin
if (ACount > 0) then
begin
GetTotal;
if ATotal <= 2 then
AppendNumber(AYear mod 100, 2)
else
AppendNumber(AYear, 4);
end else
AppendChars(@Starter, 1);
end;
else
AppendChars(@Starter, 1);
end;
end;
end;
end;
var
AStrList: TStringList;
AStr: string;
begin
BufPos := 0;
if AFormat '' then
begin
if (Pos(',',AFormat) > 0) then
begin
AStrList := TStringList.Create;
try
AStrList.CommaText := AFormat;
AStr := IfThen(ASample, AStrList[1], AStrList[0]);
AppendFormat(Pointer(AStr));
finally
AStrList.Free;
end
end else
AppendFormat(Pointer(AFormat));
end;
SetString(Result, Buffer, BufPos);
end;
sumber: http://delphindo.wordpress.com/2010/03/31/trik-menyiasati-kodifikasi-nomor-dokumen-yang-dinamis/
Tidak ada komentar:
Posting Komentar