Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts

Monday, October 31, 2011

[NAVISION] Item Card dengan Banyak Foto

Di NAV, kekurangan Item Card adalah tidak bisa menyimpan foto item lebih dari satu. Kebutuhan ini biasanya diperlukan untuk barang sparepart yang perlu foto dari beberapa sudut. Untuk mengakalinya, bisa digunakan aplikasi tambahan berupa aplikasi web yang contoh programnya akan saya tunjukan.
Pada Item Card, buat control dan beri nama Photo.
control photo
Lalu beri script berikut :

  1: 
  2: HYPERLINK('http://10.10.10.14/itempic/Default.aspx?itemno=' + "No.");
  3: 

--


Kemudian, kita buat solution di .NET. Kali ini saya menggunakan Visual studio 2005 dengan basprog C#. Lalu berikut contoh scriptnya :
Default.aspx:

  1: <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>
  2: 
  3: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  4: 
  5: <html xmlns="http://www.w3.org/1999/xhtml" >
  6: <head runat="server">
  7:     <title>Item Picture</title>
  8: </head>
  9: <body>
 10: 
 11:     <form id="form1" runat="server">
 12:     <div title="Item Picture">
 13:     <table>
 14:     <tr>
 15:     <td>
 16:         <span style="font-family: Tahoma">Item No : </span>
 17:     </td>
 18:     <td>
 19:         &nbsp;<asp:TextBox ID="TextBox1" runat="server" BorderStyle="None" Font-Names="Tahoma"></asp:TextBox></td>
 20:     </tr>
 21:      <tr>
 22:     <td>
 23:         <span style="font-family: Tahoma">
 24:     Item Name : </span>
 25:     </td>
 26:     <td>
 27:         &nbsp;<asp:TextBox ID="TextBox2" runat="server" BorderStyle="None" Font-Names="Tahoma"></asp:TextBox></td>
 28:     </tr>
 29:      <tr>
 30:     <td>
 31:         <span style="font-family: Tahoma">
 32:     Part No : </span>
 33:     </td>
 34:     <td>
 35:         &nbsp;<asp:TextBox ID="TextBox3" runat="server" BorderStyle="None" Font-Names="Tahoma"></asp:TextBox></td>
 36:     </tr>
 37:     </table>
 38:         <br />
 39:     
 40:         <table border="0" cellpadding="3" cellspacing="1" >
 41:         <tr>
 42:             <td bgcolor="#66ffff">
 43:                 <asp:Label ID="Label4" runat="server" Text="Upload foto :" Font-Names="Tahoma"></asp:Label></td>
 44:             <td bgcolor="#66ffff" colspan="3"><INPUT id="filUpload"  type="file" name="filUpload" runat="server">
 45:       <asp:Button id="btnUpload"  runat="server" Text="Upload" OnClick="btnUpload_Click" ></asp:Button>
 46:                 </td>
 47:         </tr>
 48:         <tr><td></td><td>
 49:             &nbsp;<asp:Label id="lblOutput" runat="server" Width="240px" Font-Names="Tahoma"></asp:Label></td></tr>
 50:         </table>
 51:     <table style="font-family: Tahoma">
 52:     <tr>
 53:     <td>Foto 1 :</td>
 54:     </tr>
 55:     <tr>
 56:     <td><asp:Image ID="Image1" runat="server"  /></td>
 57:     </tr>
 58:     <tr>
 59:     <td>Foto 2 :</td>
 60:     </tr>
 61:     <tr>
 62:     <td><asp:Image ID="Image2" runat="server"  /></td>
 63:     </tr>
 64:     <tr>
 65:     <td>Foto 3 :</td>
 66:     </tr>
 67:     <tr>
 68:     <td><asp:Image ID="Image3" runat="server"  /></td>
 69:     </tr>
 70:     <tr>
 71:     <td>Foto 4 :</td>
 72:     </tr>
 73:     <tr>
 74:     <td><asp:Image ID="Image4" runat="server"  /></td>
 75:     </tr>
 76:     <tr>
 77:     <td>Foto 5 :</td>
 78:     </tr>
 79:     <tr>
 80:     <td><asp:Image ID="Image5" runat="server"  /></td>
 81:     </tr>
 82:     </table>
 83:     </div>
 84:     </form>
 85: </body>
 86: </html>
 87: 

Default.aspx.cs :
  1: using System;
  2: using System.Data;
  3: using System.Configuration;
  4: using System.Web;
  5: using System.Web.Security;
  6: using System.Web.UI;
  7: using System.Web.UI.WebControls;
  8: using System.Web.UI.WebControls.WebParts;
  9: using System.Web.UI.HtmlControls;
 10: using System.Drawing;
 11: 
 12: using XYZPIC.Services;
 13: using XYZPIC.Data;
 14: using XYZPIC.Data.Bases;
 15: using XYZPIC.Entities;
 16: 
 17: public partial class _Default : System.Web.UI.Page 
 18: {
 19:     protected void Page_Load(object sender, EventArgs e)
 20:     {
 21:         if (Request.QueryString["itemno"] != null)
 22:         {
 23:             ViewState["itemno"] = Request.QueryString["itemno"].ToString();
 24: 
 25:             SafeNameXYZItem item = new SafeNameXYZItem();
 26: 
 27:             TList<SafeNameXYZItem> itemlist = new TList<SafeNameXYZItem>();
 28:             item = DataRepository.SafeNameXYZItemProvider.GetByNo(ViewState["itemno"].ToString());
 29:             TextBox1.Text = item.No;
 30:             TextBox2.Text = item.Description;
 31:             TextBox3.Text = item.PartNo;
 32: 
 33:             Image1.ImageUrl = "Image/noimage.jpg";
 34: 
 35:             Image2.ImageUrl = "Image/noimage.jpg";
 36: 
 37:             Image3.ImageUrl = "Image/noimage.jpg";
 38: 
 39:             Image4.ImageUrl = "Image/noimage.jpg";
 40: 
 41:             Image5.ImageUrl = "Image/noimage.jpg";
 42: 
 43:             TList<ItemPicture> itempicturelist = new TList<ItemPicture>();
 44:             ItemPictureQuery qry = new ItemPictureQuery();
 45:             qry.Append(ItemPictureColumn.Itemno, ViewState["itemno"].ToString());
 46:             itempicturelist = DataRepository.ItemPictureProvider.Find(qry);
 47:             int i = 1;
 48:             foreach (ItemPicture ip in itempicturelist)
 49:             {
 50:                 if (i == 1)
 51:                     Image1.ImageUrl = ip.Path;
 52: 
 53:                 if (i == 2)
 54:                     Image2.ImageUrl = ip.Path;
 55: 
 56:                 if (i == 3)
 57:                     Image3.ImageUrl = ip.Path;
 58: 
 59:                 if (i == 4)
 60:                     Image4.ImageUrl = ip.Path;
 61: 
 62:                 if (i == 5)
 63:                     Image5.ImageUrl = ip.Path;
 64: 
 65:                 i++;
 66:             }
 67:         }
 68:     }
 69: 
 70:     public bool ThumbnailCallback()
 71:     {
 72:         return false;
 73:     }
 74: 
 75:     protected void btnUpload_Click(object sender, EventArgs e)
 76:     {
 77:         string sSavePath;
 78:         sSavePath = "Image/";
 79: 
 80:         // If file field isn�t empty
 81:         if (filUpload.PostedFile != null)
 82:         {
 83:             // Check file size (mustn�t be 0)
 84:             HttpPostedFile myFile = filUpload.PostedFile;
 85:             int nFileLen = myFile.ContentLength;
 86:             if (nFileLen == 0)
 87:             {
 88:                 lblOutput.Text = "There wasn't any file uploaded.";
 89:                 return;
 90:             }
 91: 
 92:             // Check file extension (must be JPG)
 93:             if (System.IO.Path.GetExtension(myFile.FileName).ToLower() != ".jpeg")
 94:             {
 95:                 if (System.IO.Path.GetExtension(myFile.FileName).ToLower() != ".jpg")
 96:                 {
 97:                     lblOutput.Text = "The file must have an extension of JPG/JPEG";
 98:                     return;
 99:                 }
100:             }
101:             // Read file into a data stream
102:             byte[] myData = new Byte[nFileLen];
103:             myFile.InputStream.Read(myData, 0, nFileLen);
104: 
105:             // Make sure a duplicate file doesn�t exist.  If it does, keep on appending an incremental numeric until it is unique
106:             string sFilename = System.IO.Path.GetFileName(myFile.FileName);
107:             int file_append = 0;
108:             while (System.IO.File.Exists(Server.MapPath(sSavePath + sFilename)))
109:             {
110:                 file_append++;
111:                 sFilename = System.IO.Path.GetFileNameWithoutExtension(myFile.FileName) + file_append.ToString() + ".jpg";
112:             }
113: 
114:             // Save the stream to disk
115:             System.IO.FileStream newFile = new System.IO.FileStream(Server.MapPath(sSavePath + sFilename), System.IO.FileMode.Create);
116:             newFile.Write(myData, 0, myData.Length);
117:             newFile.Close();
118: 
119:             // Check whether the file is really a JPEG by opening it
120:             System.Drawing.Image.GetThumbnailImageAbort myCallBack = new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
121:             Bitmap myBitmap;
122:             try
123:             {
124:                 myBitmap = new Bitmap(Server.MapPath(sSavePath + sFilename));
125: 
126:                 //insert ke table item_picture
127:                 ItemPicture ip = new ItemPicture();
128:                 ip.Itemno = ViewState["itemno"].ToString();
129:                 ip.Path = sSavePath + sFilename ;
130:                 ip.Validate();
131:                 if (IsValid)
132:                 {
133:                     DataRepository.Provider.ItemPictureProvider.Save(ip);
134:                 }
135: 
136:                 TList<ItemPicture> itempicturelist = new TList<ItemPicture>();
137:                 ItemPictureQuery qry = new ItemPictureQuery();
138:                 qry.Append(ItemPictureColumn.Itemno, ViewState["itemno"].ToString());
139:                 itempicturelist = DataRepository.ItemPictureProvider.Find(qry);
140:                 int i = 1;
141:                 foreach (ItemPicture ip2 in itempicturelist)
142:                 {
143:                     if (i == 1)
144:                         Image1.ImageUrl = ip2.Path;
145: 
146:                     if (i == 2)
147:                         Image2.ImageUrl = ip2.Path;
148: 
149:                     if (i == 3)
150:                         Image3.ImageUrl = ip2.Path;
151: 
152:                     if (i == 4)
153:                         Image4.ImageUrl = ip2.Path;
154: 
155:                     if (i == 5)
156:                         Image5.ImageUrl = ip2.Path;
157: 
158:                     i++;
159:                 }
160: 
161:                 // Displaying success information
162:                 lblOutput.Text = "File uploaded successfully!";
163: 
164:                 // Destroy objects
165:                 //myThumbnail.Dispose();
166:                 myBitmap.Dispose();
167:             }
168:             catch (ArgumentException errArgument)
169:             {
170:                 // The file wasn't a valid jpg file
171:                 lblOutput.Text = "The file wasn't a valid jpg file.";
172:                 System.IO.File.Delete(Server.MapPath(sSavePath + sFilename));
173:             }
174:         }
175:     }
176: }
177: 
Itu saja.

Tuesday, October 14, 2008

Prinsip Main Rakit Asumsi Sendiri

"Saya menutup telepon dan seketika menyadari sesuatu: tangan saya gemetar. Saya marah. Saya murka. Merasa privasi saya diterjang dan diobrak-abrik. Orang itu datang ke teritori pribadi saya, berbekal asumsi yang ia rakit dari info sepotong, kemudian dengan gagah berani mengusung panji kebenarannya sendiri. Persis prinsip orang main hakim sendiri, tanpa ba-bi-bu merajam sang tersangka tanpa perlu memproses lebih lanjut. Senjatanya bukan batu, melainkan kata-kata. Merenungi itu semua dada saya pun sesak. Sesuatu bergolak sangat hebat."

Penggalan diatas saya ambil dari tulisan Dewi Lestari diblognya. Menarik, karena didalam software development, prinsip main rakit asumsi sendiri untuk membuat user specification, sering terjadi.

Dibilang Dee, "berbekal asumsi yang ia rakit dari info sepotong, kemudian dengan gagah berani mengusung panji kebenarannya sendiri."

Nah, kalau diubah sedikit menjadi, "berbekal asumsi yang ia rakit dari info sepotong, kemudian dengan gagah berani mengusung user specification sendiri." Itu terjadi dibeberapa Senior developer atau system analist khususnya mereka yang saya tahu dan selama saya bekerja lebih dari 5 tahun berkecimpung di IT.

Sering banget saya menemukan hal seperti itu. Punya info sedikit, lalu dengan pedenya berasumsi sebuah flow proses bisnis adalah ini, ini dan ini. Tapi, setelah diimplementasi dan user mencoba, ternyata bukan ini, ini dan ini. Malah itu, ini dan itu.

Sakit hati? Jelas.
Capek? Pasti.
Emosi? Ga perlu. Selama saya masih jadi kopral, perintah komandan mesti dijalankan, meskipun cuma berbekal bambu runcing sedangkan lawan menggunakan Bazoka.

Yang jadi pertanyaan, kenapa bisa begitu? Asumsinya ada dua:
1. Senior developer atau System Analist malu(males) bertanya, yang berakibat sesat dikerjaan.
2. Senior developer atau System Analist memang kelewat pede.

Solusinya?
Seperti tadi saya bilang: Selama masih jadi kopral, perintah komandan mesti dijalankan, apa pun itu meski berbekal bambu runcing sedangkan lawan menggunakan Bazoka.

Tuesday, September 9, 2008

Membuat Limited Access Per Group di Axapta 4.0

Sebetulnya, saya tidak tertarik untuk menulis yang berbau teknikal. Apalagi kerjaan. Tapi, berhubung kerjaan saya kali ini sedikit merangsang alias menantang, ada sedikit unsur-unsur nge-hack Axapta, maka hasil dari kerjaan ini kepingin saya share ke umum melalui blog ini.

Saya ditugaskan untuk memberi batasan bagi user yang masuk ke axapta per group. Misal, kalau group sales, punya jumlah user = 10, tapi ingin dibatesin yang boleh login cuma 5, jadi kalau orang ke 6 login untuk group tersebut, langsung di tendang oleh Axapta. nah, pembatasan seperti ini, di aplikasi Standar axapta tidak ada. Wajib membuat modifikasinya.

Pertama, rancang dulu table untuk menampung group yang dikhususkan bagi modifikasi limited user per group ini. Contohnya bisa dilihat di table sysUserGroupList dan SysUserGroupInfo.

Table: ABCUserGroupList
userid - string
ABCgroupid - string

Table: ABCUserGroupInfo
id - string
name - string
total - int (maximum user login)

Kedua, Buat form untuk user interface table ABCUserGroupInfo. Contohnya:



Buat form untuk user interface table ABCUserGroupList. Untuk membuat form ini, bisa mencontek dari Form tutorial_ListPanel. Hasilnya:



Selanjutnya, mulai buat code di class SysStartupCmd untuk proses menjalankan perintah kala startup Axapta.

case 'limitABCuser':
sysStartupCmd = new SysStartupCmdLimitABCUser(s,parm);
break;



Buat class baru SysStartupCmdLimitABCUser :

class SysStartupCmdLimitABCUser extends SysStartupCmd

{
}


void applInit()
{
Args args;
FormRun formRun;

SysClientSessions _SysClientSessions;
ABCUserGroupList _ABCUserGroupList;
ABCUserGroupList _ABCUserGroupList2;
ABCUserGroupInfo _ABCUserGroupInfo;
xSession session;
int x, y;
int maxSession ;
;


session = new xSession();
x = 0;
y = 0;
while select * from _ABCUserGroupList
where _ABCUserGroupList.userid == session.userId()
{
x++;
}

if ( x > 0 )
{
select ABCgroupid from _ABCUserGroupList
where _ABCUserGroupList.userid == session.userId() ;

select total from _ABCUserGroupInfo
where _ABCUserGroupInfo.id == _ABCUserGroupList.ABCgroupid;

maxSession = _ABCUserGroupInfo.total;

// cek di syssession

while select * from _SysClientSessions
join _ABCUserGroupList2
where _SysClientSessions.userId == _ABCUserGroupList2.userid
&& _SysClientSessions.Status == 1
&& _ABCUserGroupList2.ABCgroupid == _ABCUserGroupList.ABCgroupid
{
y++;
}

if ( y > maxSession )
{
this.shutdown();
}
}
}


---
Jika sudah menambahkan code diatas, sekarang masuk ke Axapta configuration utility, lalu tambahkan perintah "limitABCuser" di Command to run at application startup.

Setelah itu, tinggal ditutup Axapta clientnya lalu dibuka kembali untuk melihat hasilnya.

***

Note: Kode ABC adalah kode untuk kode projek anda. Bisa diganti sesuai kode projek.