<!--- Tag Parameters --->
<CFPARAM NAME="ATTRIBUTES.Processor" TYPE="string" DEFAULT="CyberCash">
<CFPARAM NAME="ATTRIBUTES.MerchList" TYPE="string">
<CFPARAM NAME="ATTRIBUTES.QuantList" TYPE="string">
<CFPARAM NAME="ATTRIBUTES.ContactID" TYPE="numeric">
<CFPARAM NAME="ATTRIBUTES.CreditCard" TYPE="string">
<CFPARAM NAME="ATTRIBUTES.CreditExpM" TYPE="string">
<CFPARAM NAME="ATTRIBUTES.CreditExpY" TYPE="string">
<CFPARAM NAME="ATTRIBUTES.CreditName" TYPE="string">
<CFPARAM NAME="ATTRIBUTES.ShipAddress" TYPE="string">
<CFPARAM NAME="ATTRIBUTES.ShipCity" TYPE="string">
<CFPARAM NAME="ATTRIBUTES.ShipCity" TYPE="string">
<CFPARAM NAME="ATTRIBUTES.ShipState" TYPE="string">
<CFPARAM NAME="ATTRIBUTES.ShipZIP" TYPE="string">
<CFPARAM NAME="ATTRIBUTES.ShipCountry" TYPE="string">
<CFPARAM NAME="ATTRIBUTES.HTMLMail" TYPE="boolean">
<CFPARAM NAME="ATTRIBUTES.ReturnVariable" TYPE="variableName">

<CFTRY>
  <!--- Make sure the MerchList and QuantList Attributes make sense --->
  <CFIF (ListLen(ATTRIBUTES.MerchList) EQ 0)
    OR ListLen(ATTRIBUTES.MerchList) NEQ ListLen(ATTRIBUTES.QuantList)>
    <!--- If not, throw an error --->
    <CFTHROW
      MESSAGE="Invalid MerchList or QuantList attribute"
      DETAIL="Both must have same number of list elements, and cannot be empty.">
  </CFIF>
  
  <!--- Quick query to verify the ContactID is valid --->
  <CFQUERY NAME="GetCount" DATASOURCE="#REQUEST.DataSource#">
    SELECT Count(*) AS ContactCount 
    FROM Contacts
    WHERE ContactID = #ATTRIBUTES.ContactID#
  </CFQUERY>
  
  <!--- If any of the MerchIDs are not valid, throw custom error --->
  <CFIF GetCount.ContactCount NEQ 1>
    <CFTHROW
      TYPE="ows.MerchOrder.InvalidContactID"
      MESSAGE="Invalid Contact ID"
      DETAIL="The ContactID you provided (#ATTRIBUTES.ContactID#) is not valid."
      ERRORCODE="1">
  </CFIF>
  
  <!--- Quick query to verify that all MerchIDs are valid --->
  <CFQUERY NAME="GetCount" DATASOURCE="#REQUEST.DataSource#">
    SELECT Count(*) AS ItemCount
    FROM Merchandise
    WHERE MerchID IN (#ATTRIBUTES.MerchList#)
  </CFQUERY>
  
  <!--- If any of the MerchIDs are not valid, throw custom error --->
  <CFIF GetCount.ItemCount NEQ ListLen(ATTRIBUTES.MerchList)>
    <CFTHROW
      TYPE="ows.MerchOrder.InvalidMerchID"
      MESSAGE="Invalid Merchandise ID"
      DETAIL="At least one of the MerchID values you supplied is not valid."
      ERRORCODE="2">
  </CFIF>

  <!--- If any database problems came up during above validation steps --->
  <CFCATCH TYPE="Database">
    <CFTHROW
      TYPE="ows.MerchOrder.ValidationFailed"
      MESSAGE="Order Validation Failed"
      DETAIL="A database problem occured while attempting to validate the order.">
  </CFCATCH>
</CFTRY>

<!--- Begin "order" database transaction here --->
<!--- Can be rolled back or committed later --->
<CFTRANSACTION ACTION="BEGIN">
  <CFTRY>
    <!--- Insert new record into Orders table --->
    <CFQUERY DATASOURCE="#REQUEST.DataSource#">
      INSERT INTO MerchandiseOrders (
        ContactID, 
        OrderDate, 
        ShipAddress, ShipCity,
        ShipState, ShipZip, 
        ShipCountry)
      VALUES (
        #ATTRIBUTES.ContactID#, 
        <CFQUERYPARAM CFSQLTYPE="CF_SQL_TIMESTAMP" VALUE="#DateFormat(Now())# #TimeFormat(Now())#">, 
        '#ATTRIBUTES.ShipAddress#', '#ATTRIBUTES.ShipCity#',
        '#ATTRIBUTES.ShipState#', '#ATTRIBUTES.ShipZip#', 
        '#ATTRIBUTES.ShipCountry#'
      )
    </CFQUERY>  
      
    <!--- Get just-inserted OrderID from database --->
    <CFQUERY DATASOURCE="#REQUEST.DataSource#" NAME="GetNew">
      SELECT MAX(OrderID) AS NewID
      FROM MerchandiseOrders
    </CFQUERY>
    
    <!--- For each item in user's shopping cart --->
    <CFLOOP FROM="1" TO="#ListLen(ATTRIBUTES.MerchList)#" INDEX="i">
      <CFSET ThisMerchID = ListGetAt(ATTRIBUTES.MerchList, i)>
      <CFSET ThisQuant   = ListGetAt(ATTRIBUTES.QuantList, i)>
      
      <!--- Add the item to "OrdersItems" table --->
      <CFQUERY DATASOURCE="#REQUEST.DataSource#">
        INSERT INTO MerchandiseOrdersItemsf
          (OrderID, ItemID, OrderQty, ItemPrice)
        SELECT
          #GetNew.NewID#, MerchID, #ThisQuant#, MerchPrice
        FROM Merchandise
        WHERE MerchID = #ThisMerchID#
      </CFQUERY>
    </CFLOOP>
    
    <!--- Get the total of all items in user's cart --->
    <CFQUERY DATASOURCE="#REQUEST.DataSource#" NAME="GetTotal">
      SELECT SUM(ItemPrice * OrderQty) AS OrderTotal
      FROM MerchandiseOrdersItems
      WHERE OrderID = #GetNew.NewID#
    </CFQUERY>
  
    <!--- Attempt to process the transaction  --->
    <CF_ProcessPayment
      Processor="CyberCash"
      OrderID="#GetNew.NewID#"
    	OrderAmount="#GetTotal.OrderTotal#"
    	CreditCard="#ATTRIBUTES.CreditCard#"
    	CreditExpM="#ATTRIBUTES.CreditExpM#"
      CreditExpY="#ATTRIBUTES.CreditExpY#"
    	CreditName="#ATTRIBUTES.CreditName#"
      ReturnVariable="ChargeInfo">
  
    <!--- If the order was processed successfully --->
    <CFIF ChargeInfo.IsSuccessful>
      <!--- Commit the transaction to database --->
      <CFTRANSACTION ACTION="Commit"/>
    <CFELSE> 
      <!--- Rollback the Order from the Database --->
      <CFTRANSACTION ACTION="RollBack"/>
    </CFIF>  

    <!--- If any errors occur while processing the order --->  
    <CFCATCH TYPE="Any">
      <!--- Rollback the Order from the Database --->
      <CFTRANSACTION ACTION="RollBack"/>
      <!--- Throw a custom exception --->
      <CFTHROW
        TYPE="ows.MerchOrder.OrderFailed"
        MESSAGE="Order Could Not Be Completed"
        DETAIL="The order (ID #GetNew.NewID#) was rolled back from the database."
        ERRORCODE="3">
    </CFCATCH>
  </CFTRY>
</CFTRANSACTION>

<!--- If the order was processed successfully --->
<CFIF ChargeInfo.IsSuccessful>
  <!--- Send Confirmation E-Mail, via Custom Tag --->
  <CF_SendOrderConfirmation
    OrderID="#GetNew.NewID#"
    UseHTML="#ATTRIBUTES.HTMLMail#">  
</CFIF>

<!--- Return status values to callling template --->
<CFSET "Caller.#ATTRIBUTES.ReturnVariable#" = ChargeInfo>