• Tidak ada hasil yang ditemukan

Building An Online Shopping Cart Using C Sharp And Asp Net Part 1

N/A
N/A
Protected

Academic year: 2019

Membagikan "Building An Online Shopping Cart Using C Sharp And Asp Net Part 1"

Copied!
16
0
0

Teks penuh

(1)

Edit or 's N ot e : Th is a r t icle ' s code h a s be e n u pda t e d t o w or k w it h t h e fin a l r e le a se of t h e .N e t fr a m e w or k .

As w eb developers w e are required t o face a w ide variet y of applicat ion needs. Each w eb sit e developed is unique and furnished according t o each client 's specific needs. The fact is t hat w ebsit es are indeed fabricat ed for each client w it h different specificat ions but every sit e shares som e com m on charact erist ics. Those part s of t he sit e t hat share funct ionalit y feat ures can be t reat ed as separat e applicat ions t o be reused.

I n t his case w e w ill address t he developm ent cycle for one of t he com m on blocks in t oday's w ebsit es - an Online Shopping Cart .

We w ill analyze t he developm ent of a shopping cart as a group of com ponent s described clearly before w e im plem ent t hem , t hus allow ing us t o use t his know ledge in areas ot her t han ASP.NET. Aft er a descript ion of each com ponent t he im plem ent at ion w ill be explained using C# .

The applicat ion w ill be designed t o w ork w it h a SQLServer dat abase for st orage. Applicat ion logic w ill be done w it hin t he Web Form and present ed t o t he user t hrough t he w eb brow ser. Core logic w ill reside in a separat e C#

CATEGORY: Applicat ion Developm ent

ARTI CLE TYPE: Tut orial Reader Com m ent s I n t his art icle Juan Mart ínez discusses and im plem ent s t he building blocks of an online shopping cart -

covering in t his part it em cat alogs, it em det ails, a cart and a checkout syst em . This act s as t he foundat ion for fur t her ar t icles, w here Juan covers ot her funct ionalit y like adm inist rat ion pages and set t ing up credit card paym ent s.

Art icle Discussion Rat e t his ar t icle Relat ed Links I ndex Ent ries

(2)

Aft er t hese st eps w e w ill have a clear pat h of developm ent and be ready t o im plem ent our online shopping cart in t he C# language.

D iggin g in t h e On lin e Sh oppin g Ca r t M ode l

We w ill first t ake a look at a sim plified diagram of an Online Shopping Cart . These are t he funct ionalit y blocks t o be discussed.

We t hen have four basic m odules:

z I t e m Ca t a log - Her e w e display t he opt ions t o our client s in an or ganized w ay.

z I t e m D e t a ils - Here w e show t he client as m uch info as w e can t o show off our product .

z Sh oppin g Ca r t - Here we m anage t he user's select ed it em s.

z Ch e ck ou t Sy st e m - Her e w e save t he it em s select ed and t he client 's infor m at ion t o close t he t ransact ion.

These are t he basic blocks t o be im plem ent ed in our online st ore. I t includes t he indispensable funct ionalit y t hat w ill be described in det ail lat er. These blocks could be enriched furt her w it h m ore feat ures, w hich w ill be covered in lat er art icles.

D e fin in g r e qu ir e m e n t s

As in every soft w are developm ent cycle, w e need t o define our requirem ent s first so w e can design soft w are capable of giving sat isfact ion t o our cust om ers.

Our online shopping cart applicat ion should do t he follow ing:

z Have a list of cat egories and subcat egories.

z I t em s should be ar r anged in it s corresponding subcat egory.

z I t em s could be select ed for cat egory and hom e prom ot ion.

z Each product should have an id, nam e, shor t and long descript ions, sm all and lar ge im ages, st ock and price.

z Users should be able t o add product s t o t he basket and rem ove t hem .

z The user should be given an order num ber and w ill be able t o t rack it t hrough an order t racking syst em .

(3)

From our requir em ent s w e define t he dat abase schem a. The t ables ar e show n as a concept ual m odel, w it h all t ables used in t his version of t he shopping cart .

The t ables ar e gr ouped as follow s:

z Green - The cat alog part of our applicat ion.

z Sky blue - I t em det ails.

z Orange - Shopping cart basket .

z Yellow - The checkout syst em .

Ca t a log Se ct ion

(4)

sect ion/ subsect ion approach. As t his approach will work in m ost cases, you could im prove t his t o a com plet ely flexible design using r ecur sive sect ions, which will inherit a parent I d.

I t e m D e t a ils

The it em det ails part of our m odel is a t rim m ed down version of an it em det ails design. We have only one t able in which we save t he vit al inform at ion of t he it e m such as descript ion, price and im ages. We have a couple of Boolean values t hat are used t o specify if t he it em should be displayed as a hom e or sect ion it em .

Sh oppin g ca r t ba sk e t

The shopping basket is a sim ple t able t hat is used t em por ar ily t o st or e t he it em s select ed by t he user . We j ust save t he se ssion I d, t he it e m id and t he qu a n t it y. We will im plem ent t his as an in - m e m or y da t a t a ble and hold our select ed it em s in a session var iable. This t able is show n t o show you're t he inform at ion t hat needs t o be ret ained during our session.

Ch e ck ou t syst e m

This is t he m ost com plicat ed par t or our syst em . Upon checkout w e creat e an order I d in t he order t able. Then t he it em s st ored in t he shopping basket are t ransferred and saved in our order I t em s t able. The user inform at ion is st or ed in t he order det ails t able. These t w o t ables inher it t he order I d. We have a fourt h t able which also inherit s t he order I d. This is t he order Progress t able and it is used for order t racking. As progress is done, t he online shop adm inist rat or should add a record t o t his t able indicat ing t he progress done t o dat e. This is t hen checked by t he buyer.

Le t t h e codin g be gin

As our design basis is done, w e are all set t o st art our coding. The archit ect ure will be based on sim ple Web Form s calling cust om User Cont rols. Core logic w ill be done in separat e com ponent s using t he code behind t echnique.

Applica t ion fr a m e w or k

We st art by set t ing our basic fram ew ork. We m ake use of our

web.config

file t o save im port ant applicat ion inform at ion such as our connect ion st ring. This is how our configurat ion file will look:

<configuration>

<appSettings>

<add key="connString" value="server=(local)\NetSDK;database=ShoppingCart;Trusted_Con

</appSettings>

</configuration>

To r et rieve t his inform at ion w e use t he follow ing code snippet .

String connString = ConfigurationSettings.AppSettings["connString"];

As you can see, t his is a very easy and convenient w ay t o st ore applicat ion w ise dat a.

Ca t e gor y List Block

All being set , w e have our first t ask w hich is t o display a list of pr oduct s w hich w ill be filt ered by sect ion and subsect ion if select ed.

The first t ask is t o set up t he w orkspace of our Web Form s. We set up our language and add t he appropriat e nam espaces for our code t o w ork.. We set C# as our language and im port t he

System

nam espace for general purposes. We t hen add t he

System.Data

and

System.Data.OleDb

since w e w ill be using SQLSer ver as our dat abase engine. We should set t he debug flag t o false once w e deliver t his applicat ion t o t he real w orld.

<%@ Page Language="C#" Debug="true" %>

<%@ Import Namespace="System" %>

<%@ Import Namespace="System.Data" %>

<%@ Import Namespace="System.Data.SqlClient " %>

(5)

<%@ Register TagPrefix="SC" TagName="Site" Src="uc_header.ascx" %>

cont rol,

uc_catalog_section.ascx

w hich displays t he list of sect ions available on t he sit e. This is done by binding a dat a ret rieval codebehind class t o t he user cont rol.

This is our User Cont rol Code:

<%@ Control Language="C#" Debug="true" Inherits="CodeBehind.UcSection" %>

<%@ Import Namespace="System.Data" %>

(6)

<html>

<head>

<title></title>

<script language="C#" runat="server"></script>

</head>

<body>

<font face="Verdana" size="-1">

<asp:DataList id="MySectionList" runat="server"

BorderColor="black"

<a href="catalog.aspx?sectionId=<%# DataBinder.Eval(Container.DataItem,"ca

&sectionIndex=<%#Cont

inform at ion. The

<%# DataBinder.Eval(Container.DataItem, "catalogSectionName") %>

code is used t o select specific inform at ion from t he bound dat a and put it in place.

protected void Page_Load(object sender, EventArgs e) {

if (!IsPostBack) {

Bind_MySectionList();

}

if (Request.QueryString["sectionIndex"] != null) {

MySectionList.SelectedIndex = Int32.Parse(Request.QueryString["sectionIndex"]);

}

}

protected void Bind_MySectionList() {

String connString = ConfigurationSettings.AppSettings["connString"];

SqlConnection myConnection = new SqlConnection(connString);

SqlDataAdapter myCommand = new SqlDataAdapter("SELECT catalogSectionId, catalogSecti

FROM catalogSection ORDER BY catalogSectionName", myConnec

DataSet ds = new DataSet();

(7)

MySectionList.DataSource = new DataView(ds.Tables[0]);

MySectionList.DataBind();

}

}

We t hen have t o im plem ent our su bse ct ion u se r con t r ol. This cont rol w ill do a sim ilar t ask t o t he sect ion cont rol. We w ill j ust add a filt er t o t he Query applied t o t he dat abase. We will select subsect ions corresponding t o t he select ed sect ion. The rest is pret t y m uch t he sam e.

"SELECT catalogSubSectionId, catalogSubSectionName FROM catalogSubSection WHERE catalogS

sectionId + " ORDER BY catalogSub

We t hen need t o display our product list . We have t hr ee t ypes of pr oduct s:

z Sit e Product s: These are shown if no sect ion is select ed

z Sect ion Product s: These are shown if a sect ion is select ed but no subsect ion is select ed.

z Nor m al Product s: These ar e product s t hat belong t o t he select ed subsect ion.

We need t o filt er t he t hree possibilit ies and creat e t he proper query. This is done in t he

UcProductList

class w it h t his code. Aft er w e have our query w e bind it t o a Dat aGr id Web Cont rol t o display t he it em s in a t able arrangem ent .

string SQLQuery = "SELECT itemId, itemName, itemShortDescription, itemSmallImage, itemPr

FROM item WHERE itemPromoteSite=1 ORDER

int mysectionId = 0;

if (Request.QueryString["sectionId"] != null) {

mysectionId = Int32.Parse(Request.QueryString["sectionId"]);

}

if (mysectionId != 0) {

//If we have a section selected we filter products for this section

SQLQuery = "SELECT item.itemId, item.itemName, item.itemShortDescription, item.itemSma

FROM (catalogSection INNER JOIN catalogSubSection ON catalogSection.catalogSectionI

INNER JOIN item ON catalogSubSection.catalog

WHERE (((catalogSection.catalogSectionId)=" + mysectionId + "

}

int mysubsectionId = 0;

if (Request.QueryString["subsectionId"] != null) {

mysubsectionId = Int32.Parse(Request.QueryString["subsectionId"]);

}

if (mysubsectionId != 0) {

//If we have a subsection selected we filter products for this subsection

SQLQuery = "SELECT itemId, itemName, itemShortDescription, itemSmallImage, itemPrice,

WHERE catalogSubSectionId=" + mysubsectionId + " ORDER BY itemName";

}

This concludes our cat alog present at ion layer which consist s of four m ain user cont rols.

z The first cont rol is responsible for displaying a list of sect ions.

z The second cont rol is responsible for t he subsect ion list .

z The t hird cont rol is responsible for displaying a grid of it em s. This list of it em s is ret rieved from one of t hree sql queries depending on t he sit uat ion.

z A final cont rol renders t he t op of t he page.

All t he cont r ols w or k t oget her t o for m

catalog.aspx

. The user cont r ols m ake use of codebehind classes for dat abase access and bind t he Dat aList s in our page.

(8)

I t e m D e t a ils

Our next st ep in building our shopping cart is t o show off t he it em det ails. We first w ill use som e of t he code done for t he cat alog present at ion before. We w ill t ake t he basic ht m l fram ew ork and t hree user cont rols. We will reuse t he header, sect ion and subsect ion cont r ol.

The difference here w ill be t o replace t he it e m list cont rol w it h a ne w it e m de t a ils cont r ol. We w ill use a dat a list Web Cont rol t o display t he it em s charact erist ics as well as it s cor r esponding class in our code behind reposit ory.

The code t o do t his sim ple t ask is as follow s for t he user cont r ol:

<%@ Control Language="C#" Debug="true" Inherits="CodeBehind.UcItemDetails" %>

<%@ Import Namespace="System.Data" %>

<%@ Import Namespace="System.Data.SqlClient" %>

<script language="C#" runat="server"></script>

<font face="Verdana" size="-1">

<asp:DataList id="MyItemDetails" runat="server"

BorderColor="black"

BorderWidth="1"

GridLines="Both"

CellPadding="3"

Font-Name="Verdana"

Font-Size="8pt"

Width="600px"

HeaderStyle-BackColor="#aaaadd"

SelectedItemStyle-BackColor="Gainsboro"

RepeatDirection = "Horizontal"

(9)

>

<ItemTemplate>

<table>

<tr>

<td valign="top">

<img src="images/<%# DataBinder.Eval(Container.DataItem, "itemLargeImage") %>" wid

</td>

<td valign="top">

<span class="itemTitle"><%# DataBinder.Eval(Container.DataItem, "itemName") %></sp

<br>

<span class="itemText"><%# DataBinder.Eval(Container.DataItem, "itemLongDescriptio

<br><br>

<span class="itemText">Price: <%# (DataBinder.Eval(Container.DataItem, "itemPrice"

<br>

<span class="itemText">Stock: <%# DataBinder.Eval(Container.DataItem, "itemStock")

<br><br>

<a href="catalog.aspx?sectionId=<%=sectionId%>&sectionIndex=<%=sectionIndex%>&subs

&subsectionIndex=<%=subsectionIndex

<span class="itemText"> | </span>

<a href="cart.aspx?cartAction=1&itemId=<%# DataBinder.Eval(Container.DataItem, "it

</td>

</tr>

</table>

</ItemTemplate>

</asp:DataList>

</font>

And our code behind class:

protected void Bind_ItemDetails() {

int myItemId = 0;

if (Request.QueryString["itemId"] != null) {

myItemId = Int32.Parse(Request.QueryString["itemId"]);

}

string SQLQuery = "SELECT itemId, itemName, itemLongDescription, itemLargeImage, itemP

FROM item WHERE itemId

String connString = ConfigurationSettings.AppSettings["connString"];

SqlConnection myConnection = new SqlConnection(connString);

SqlDataAdapter myCommand = new SqlDataAdapter(SQLQuery, myConnection);

DataSet ds = new DataSet();

myCommand.Fill(ds, "item");

MyItemDetails.DataSource = new DataView(ds.Tables[0]);

MyItemDetails.DataBind();

}

Furt her enhancem ent s can be done t o t his sim ple m odule. This form show s t he st ored det ails of t he it em and can be enriched w it h user review s and r elat ed it em list s.

(10)

Sh oppin g ca r t ba sk e t

The shopping cart basket im plem ent s t he m aj orit y of t he funct ionalit y. I t should provide w ays t o add, edit and delet e it em s from it . The basket is m erely a t em poral st orage area for t he user t o group t he it em s of int er est . We t hen need som e session m anagem ent t o be able t o r ecognize w hich it em s belong t o each client in it s ow n session.

ASP.NET, as in previous asp applicat ions, provides t he necessary obj ect s t o work wit h sessions. I n t his case we w ill t ake advant age of t he Se ssion obj ect . We will st ore a D a t a Ta ble obj ect as a Session var iable t herefor e all shopping cart basket operat ions ar e done in m em or y. This is a very fast approach but w ill need t o be provided w it h enough m em ory t o handle concurrent client s.

The shopping basket m odule com prises t w o fundam ent al part s. The fir st involves m anaging t he it em s t hat t he user w ant s t o have in t he basket . The second is in charge of displaying t he it em s current ly in t he basket . We w ill see t he det ails now .

We inst ruct our Web Form t o add an it em t o t he cart w it h queryst ring variables. We j ust add an it em t o t he Dat aTable. To im plem ent t he updat e and delet e m et hods w e bind t he Dat aTable t o t he Dat aList Web Cont rol and perform t he operat ions.

void Page_Load(Object Sender, EventArgs E) {

if (Request.QueryString["cartAction"] != null) {

this.cartAction = Int32.Parse(Request.QueryString["cartAction"]);

}

if (Session["ShoppingCart"] == null) {

Cart = new DataTable();

Cart.Columns.Add(new DataColumn("ItemId", typeof(string)));

Cart.Columns.Add(new DataColumn("Item", typeof(string)));

Cart.Columns.Add(new DataColumn("Qty", typeof(string)));

Cart.Columns.Add(new DataColumn("Price", typeof(string)));

Session["ShoppingCart"] = Cart;

(11)

Cart = (DataTable)Session["ShoppingCart"];

if (Request.QueryString["cartAction"] != null) {

myCartAction = Int32.Parse(Request.QueryString["cartAction"]);

}

String connString = ConfigurationSettings.AppSettings["connString"];

SqlConnection myConnection = new SqlConnection(connString);

protected void DataCartList_DeleteCommand1(Object Sender, DataListCommandEventArgs e

string item = ((Label)e.Item.FindControl("Label4")).Text;

CartView.RowFilter = "Item='"+item+"'";

protected void DataCartList_EditCommand1(Object Sender, DataListCommandEventArgs e)

CartList.EditItemIndex = (int)e.Item.ItemIndex;

BindCartList();

BindTotalList();

}

protected void DataCartList_CancelCommand1(Object Sender, DataListCommandEventArgs e

CartList.EditItemIndex = -1;

BindCartList();

BindTotalList();

}

protected void DataCartList_UpdateCommand1(Object Sender, DataListCommandEventArgs e

string itemId = ((Label)e.Item.FindControl("Label1")).Text;

(12)

string qty = ((TextBox)e.Item.FindControl("Text1")).Text;

string price = ((Label)e.Item.FindControl("Label3")).Text;

DataTable CartTable = (DataTable)Session["ShoppingCart"];

foreach(DataRow myRow in CartTable.Rows) {

Double tempPrice = Double.Parse(myRow[3].ToString());

Int32 tempQty = Int32.Parse(myRow[2].ToString());

mySubTotal += tempPrice * tempQty;

CartTotal.Columns.Add(new DataColumn("SubTotal", typeof(string)));

CartTotal.Columns.Add(new DataColumn("Tax", typeof(string)));

CartTotal.Columns.Add(new DataColumn("Total", typeof(string)));

DataRow drTotal = CartTotal.NewRow();

drTotal[0] = mySubTotal.ToString();

(13)

Ch e ck ou t Sy st e m

The checkout syst em has t he responsibilit y of saving t he client info and select ed it em s for processing. We use t hree t ables t o save t he client info. These are t he follow ing:

z order Dat a - St or es t he dat e of t he order and generat es t he order I d.

z orderI t em - List of it em s bought , it also saves t he pr ice at t he t im e of pur chase.

z orderDet ail - Saves shipping and billing inform at ion for t he order.

We divide our process int o t hr ee st eps:

z Shipping and Billing I nform at ion - Here w e get t he shipping inform at ion. Wit h t his info w e can calculat e t he shipping cost s. This should be done accor dingly t o each st or e's necessit ies. We validat e credit car d infor m at ion also. This should be done using a specific provider like paypal.

z Confirm at ion - Her e w e present a sum m ary of t he inform at ion received and show t he list of it em s t o be bought , as w ell as t he grand t ot al of t he order. The user is asked t o subm it t he inform at ion if it is correct .

z Sum m ary - We finish t he t ransact ion and show t he user t he order num ber.

We post t he info from t he first t o t he second st ep. We t hen use Web Form Cont rols t o ask for confirm at ion. I f t he info is correct , t hen w e regist er t he order for our client .

We do need t o im plem ent som e form validat ion before post ing t he infor m at ion and im plem ent som e credit card validat ion t hrough an ext ernal pr ovider or your ow n soft w are.

Tr a ck in g y ou r or de r

The final part of our online shopping car t applicat ion is t he t r acking syst em . We w ill im plem ent a basic t racking syst em w hich w ill ask t he user for t heir em ail and order num ber. The syst em w ill t hen show a list of m ilest ones regist ered in t he t racking dat abase.

(14)

This is t he code required:

protected void ButtonView_Click(object Source, EventArgs e) {

//Look for order id with provided email and order number

String connString = ConfigurationSettings.AppSettings["connString"];

string strSelect = "SELECT orderId FROM orderDetail WHERE orderId=" + orderIdBox.Text

AND orderDetailShippingEmail='" + emailBox.Text + "'";

SqlConnection myConnection = new SqlConnection(connString);

SqlCommand myCommand = new SqlCommand(strSelect, myConnection);

myConnection.Open();

SqlDataReader dr = myCommand.ExecuteReader();

int newOrderId = 0;

if (dr.Read()) {

//emailBox.Text = "Encontramos!!!";

Bind_TrackingList();

}

myConnection.Close();

}

protected void Bind_TrackingList() {

string SQLQuery = "SELECT orderProgressText, orderProgressDescription, orderProgressD

WHERE orderId = " + orderIdBox.Text;

String connString = ConfigurationSettings.AppSettings["connString"];

SqlConnection myConnection = new SqlConnection(connString);

SqlDataAdapter myCommand = new SqlDataAdapter(SQLQuery, myConnection);

DataSet ds = new DataSet();

myCommand.Fill(ds, "orderProgress");

MyTrackingList.DataSource = new DataView(ds.Tables[0]);

MyTrackingList.DataBind();

(15)

D e ploy m e n t of t h e sit e

Deploym ent of t his part icular applicat ion is ver y sim ple.

z Creat e a ne w da t a ba se in SQLServer online shopping cart . Furt her enhancem ent s can be m ade and w ill be t he responsibilit y of t he reader. These enhancem ent s should be m ade t o enrich t he shopping cart applicat ion give a bet t er ser vice t o t he online com m unit y. Som e ideas are present ed here.

Fe a t u r e im pr ove m e n t s

z Recursive sect ions for n levels of pr ofundit y

z I t em review s

z I t em relat ed it em s

z User account s and m anagem ent

z Mailing list t o cust om ers

z Specific shipping cost s calculat ions

Te ch n ica l im pr ove m e n t s

z Build based on com ponent s for perform ance and possible code reuse

z Migrat e t o SQL Server dat abase using st ored procedures for perform ance

z I m plem ent SSL in your server ( a m ust but out of scope! )

z I m plem ent real t im e credit card processing and charging.

Con clu sion s

The syst em present ed shows t he basis of a working online shopping cart . I t involves t he m ain aspect s of an online st ore which are t he cat alog of it em s, t he it em det ail m odule, t he shopping cart basket and t he checkout m odule. Every shopping car t online t oday m ust im plem ent t hese basic part s t o be funct ional. Hopefully t his ar t icle has given you t he know ledge t o build your own w it h ease and t o add new funct ionalit y t o m eet your needs as ideas for im provem ent have been given.

I n fut ure art icles, w e w ill cover som e of t he im port ant requirem ent s of a real - w orld shopping cart t hat have been

z See ot her art icles in t he Applicat ion Develo

z See ot her Tut orial art icles

z Reader Com m ent s on t his ar t icle

z Go t o Previous Art icle

(16)

( Opt ion a l)

ht t p: / / w ww.sybase.com / product s/ ent erprisem odeling/ pow erdesigner

z Pay Pal: w w w .paypal.com

Ecom m erce Perform ance Securit y Sit e Design XML SO

Dat a Access/ ADO.NET Applicat ion

Developm ent Web Services Graphics/ Gam es Mobile Ot her Technologies

C# Today is brought t o you by Wrox Press (w w w .w rox.com) . Please see our t erm s and condit ions and privacy C# Today is opt im ised for Microsoft I nt ernet Explorer 5 brow sers.

Referensi

Dokumen terkait

Pengadaan alat angkut darat bermotor stasion wagon Dinas Pasar 1. Biaya oprasional dan pemeliharaan

Dari hasil kesimpulan ke-4 simulasi pola operasi Embung Joho maka pola operasi yang sesuai untuk Embung Joho adalah pola operasi yang sesuai dengan simulasi

Penelitian ini bertujuan untuk menguji pengaruh rasio-rasio model Springate yaitu rasio modal kerja dibagi total aset, rasio laba sebelum beban bunga dan pajak dibagi total

Jumlah konversi pada biaya sudah sesuai dengan metode pembayaran PAMSIMAS Desa Rejosari dengan nilai rata- rata kesalahan sistem 0.003 % dan sistem monitoring SMS gateway

Kemudian, diambil lagi larutan stock baru, lalu ditambahkan NH 4 OH, NH 4 Cl, dan (NH 4 ) 2 S dan tetap tidak terjadi perubahan (Berarti bukan golongan III). Berarti sampel ini

mempersiapkan karir. Kualitas pemilihan karir ditentukan oleh tingkat kematangan karir. Harga diri dan motivasi berprestasi merupakan faktor personal yang terkait

[r]

Sesuai dengan yang dipersyaratkan dalam Dokumen Lelang, pada saat Pembuktian Kualifikasi Calon Penyedia Agar membawa :.. Dokumen Asli Perusahaan dan