Глава 12. Управление заказами
Последний компонент интерфейса управления, описанный в этой главе, предназначен для управления заказами. Мы должны предоставить менеджерам электронного магазина средства, позволяющие удобно и быстро отбирать заказы для обработки, организовать службу поддержки клиентов, установить статус отправки выполненных заказов и т. д.
Механизм поиска обеспечивает ускоренный поиск заказов, удовлетворяющих заданным критериям. Все найденные заказы выводятся в виде списка. На этой же странице создаются средства для редактирования заказов и изменения их текущего состояния.

Поиск заказов
Будем надеяться, что наш новый электронный магазин окажется популярным. Следовательно, при обработке большого количества заказов потребуются средства фильтрации и поиска. На первой странице пользователю предлагается выбрать поля заказа, значения которых используются в качестве критериев поиска. Это самый удобный и простой способ выборки заказов, удовлетворяющих некоторым критериям.
Начало страницы ввода критериев поиска приведено в листинге 12.1. Как обычно, страница включает стандартные заголовочные файлы для проверки пользователя и создания панели ссылок.
Листинг 12.1. ManageOrders.asp
<%@ Language=VBScript %>
<!-- #Include file="include/validatecheck.asp" -->
<!-- ManageOrders.asp - страница для ввода критериев, по которым осуществляется поиск заказов. -->
<HTML>
<HEAD>
<META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">
</HEAD>
<BODY>
<!-- #include file="include/navinclude.asp" -->
<!-- Форма для ввода критериев поиска. -->
<BR><BR>
<b>Enter in your search criteria:</b>
<BR><BR>
Мы создаем форму, которая передает данные странице OrderSearch.asp, и начинаем строить таблицу с текстовыми полями. В первых двух полях вводится имя покупателя и адрес электронной почты, по которым осуществляется поиск.
За ним следуют поля, предназначенные для интервального поиска по дате оформления заказа, а еще дальше - поля для интервального поиска по итоговой стоимости заказа (см. листинг 12.2).
Листинг 12.2. ManageOrders.asp (продолжение)
<form method="post" action="OrderSearch.asp">
<!-- Start the table to display the search fields. -->
<table>
<!-- Shopper name input field. -->
<tr>
<td align="right">Search by Shopper Name:</td>
<td><input type="text" name="srchShopperName" value=""></td>
</tr>
<!-- Shopper email address input field. -->
<tr>
<td align="right">Search by Shopper Email Address:</td>
<td><input type="text" name="srchShopperEmail" value=""></td>
</tr>
<!-- Fields are created to enter in a starting
date and end date. -->
<tr>
<td align="right">Search by Order Date Range:</td>
<td>
<input type="text" name="srchStartDate" value="">
<input type="text" name="srchEndDate" value="">
</td>
</tr>
<!-- Fields are created to enter in a starting
amount and end amount. -->
<tr>
<td align="right">Search by Order Total Amount:</td>
<td>
<input type="text" name="srchStartAmount" value="">
<input type="text" name="srchEndAmount" value="">
</td>
</tr>
Также может возникнуть необходимость в поиске заказов по входящим в них товарам, поэтому мы создаем текстовое поле для ввода названия товара. За ним следует кнопка отправки данных формы и закрывающие теги страницы (см. листинг 12.3).
Листинг 12.3. ManageOrders.asp (продолжение)
<!-- Поле для ввода названия товара. -->
<tr>
<td align="right">Search by Product Name:</td>
<td><input type="text" name="srchProductName" value=""></td>
</tr>
<!-- Кнопка отправки данных формы. -->
<tr>
<td colspan="2" align="Center">
<input type="Submit" value="Submit" name="Submit">
</td>
</tr>
</table>
</form>
</BODY>
</HTML>
После ввода критериев поиска данные передаются странице OrderSearch.asp (см. листинг 12.4). Страница выводит список товаров, найденных по указанным критериям.
В первой части страницы создается запрос к базе данных. На этот раз запрос строится непосредственно на VBScript без использования хранимых процедур SQL. Строка запроса генерируется во время выполнения программы.
Листинг 12.4. OrderSearch.asp
<%@ Language=VBScript %>
<!-- #Include file="include/validatecheck.asp" -->
<!--
OrderSearch.asp - Provides input fields for performing the
order search against the order data and the basket.
-->

<HTML>
<BODY>
<!-- #include file="include/navinclude.asp" -->
Работа страницы, как показано в листинге 12.5, начинается с чтения значений, введенных пользователем на форме. Содержимое полей Amount умножается на 100, чтобы оно соответствовало целочисленным значениям, хранящимся в базе данных. В строках названия товара и имени покупателя одиночные апострофы, как обычно, заменяются двойными.
Листинг 12.5. OrderSearch.asp (продолжение)
<%
' The key fields are retrieved from the order
' search page.
srchShopperName = replace(request("srchShopperName"), "'", "''")
srchShopperEmail = request("srchShopperEmail")
srchStartDate = request("srchStartDate")
srchEndDate = request("srchEndDate")
srchStartAmount = request("srchStartAmount")
srchEndAmount = request("srchEndAmount")
' Now we begin the building of the SQL statement.
' In this case instead of calling a stored procedure
' we are going to create a SQL statement based upon
' the input parameters on the search form.
' Retrieve the starting search amount
if srchStartAmount <> "" then
' Remember to mulitply the search amount
' by one hundred to make it an integer.
srchStartAmount = srchStartAmount * 100
end if
' Retrieve the ending search amount
if srchEndAmount <> "" then
' Remember to mulitply the search amount
' by one hundred to make it an integer.
srchEndAmount = srchEndAmount * 100
end if
' Retrieve the product name to search by.
srchProductName = replace(request("srchProductName"), "'", "''")
На следующей фазе поиска начинается построение запроса SQL (см. листинг 12.6). При этом используются таблицы OrderData, Basket, BasketItem и OrderStatus. Данные этих таблиц объединяются для проведения поиска.
Листинг 12.6. OrderSearch.asp (продолжение)
' Первая часть команды SQL строится автоматически.
' В запросе определяются возвращаемые поля, а ключевое слово
' Distinct используется для того, чтобы для каждого заказа
' возвращалась только одна запись. Для получения всех
' необходимых данных используется объединение основных таблиц.
sql = "select distinct orderdata.idOrder, OrderData.idShopper, dtOrdered, " & _
"chrShipLastName, chrBillLastName, chrShipEmail, " & _
"chrBillEmail, intTotal, idStage, chrShippingNum " & _
"from OrderData, Basket, basketitem, orderstatus " & _
"where OrderData.idBasket = Basket.idBasket and " & _
"BasketItem.idBasket = Basket.idBasket and " & _
"OrderStatus.idorder = orderdata.idOrder "
Далее начинается серия дополнительных проверок. Сначала проверяется адрес электронной почты (см. листинг 12.7). Если пользователь ввел адрес в критериях поиска, мы ищем похожие адреса в реквизитах доставки и выписки счета. К построенной части команды добавляется соответствующая синтаксическая конструкция SQL.
В данном примере проверяется не точное совпадение адреса электронной почты, а наличие в нем указанной строки. Это позволяет ввести критерий типа "@sybex.com" и получить все заказы, у которых в адресе электронной почты присутствует указанный образец.
Листинг 12.7. OrderSearch.asp (продолжение)
' Проверить, используется ли в критериях поиска
' адрес электронной почты.
if srchShopperEmail <> "" then
' Команда SQL дополняется конструкцией для поиска
' введенного текста в адресах электронной почты,
' указанных в реквизитах доставки и выписки счета.
' Обратите внимание на использование ключевого слова LIKE.
sql = sql & " and (" & _
"chrShipEmail like '%" & srchShopperEmail & "%' or " & _
"chrBillEmail like '%" & srchShopperEmail & "%') "
end if
Следующая проверка относится к имени покупателя. На этот раз искомый текст также может находиться в нескольких полях. В данном примере поиск осуществляется в полях имени и фамилии, указанных в реквизитах доставки и выписки счета. При проведении поиска используется ключевое слово SQL LIKE. Обратите внимание - условия поиска объединяются операцией OR, чтобы результат возвращался при обнаружении искомого текста хотя бы в одном из полей (см. листинг 12.8).
Листинг 12.8. OrderSearch.asp (продолжение)
' Затем проверяется поле имени покупателя. Если
' в нем присутствует текст, мы снова при помощи
' команды LIKE проверяем, присутствует ли текст
' хотя бы в одном имени или фамилии, указанных
' в реквизитах доставки и выписки счета.
if srchShopperName <> "" then
sql = sql & "and ( " & _
"chrShipFirstName like '%" & srchShopperName & "%' or " & _
"chrShipLastName like '%" & srchShopperName & "%' or " & _
"chrBillFirstName like '%" & srchShopperName & "%' or " & _
"chrBillLastName like '%" & srchShopperName & "%') "
end if
В листинге 12.9 проверяется нижняя и верхняя граница даты оформления заказа. Мы проверяем каждое поле, чтобы узнать, был ли в нем введен какой-либо текст. Если текст присутствует, в запрос SQL включается сравнение поля dtOrdered с введенной датой (или датами).
Листинг 12.9. OrderSearch.asp (продолжение)
' Проверить верхнюю границу даты. Если ее
' значение было введено на форме, запрос SQL
' обновляется соответствующим условием
if srchStartDate <> "" then
sql = sql & " and dtOrdered >= '" & srchStartDate & "' "
end if
' Next we check the ending date for the search. If it
' is set then the SQL query is updated.
if srchEndDate <> "" then
sql = sql & " and dtOrdered <= '" & srchEndDate & "' "
end if
Аналогичная проверка выполняется и для поиска по итоговой стоимости заказа, чтобы в запросе SQL итоговая сумма проверялась на принадлежность к заданному интервалу. Соответствующие условия включаются в создаваемую команду SQL (см. листинг 12.10).
Листинг 12.10. OrderSearch.asp (продолжение)
' Проверить, ввел ли пользователь нижнюю границу
' итоговой стоимости заказа. Если граница введена,
' обновить запрос.
if srchStartAmount <> "" then
sql = sql & " and intTotal >= " & srchStartAmount
end if

' Проверить верхнюю границу итоговой стоимости.
' Если граница введена, обновить запрос.
if srchEndAmount <> "" then
sql = sql & " and intTotal <= " & srchEndAmount
end if
Наконец, в листинге 12.11 проверяется название товара. Как и прежде, команда SQL LIKE проверяет, совпадает ли искомый текст с произвольной частью названия товара.
Листинг 12.11. OrderSearch.asp (продолжение)
' Проверить, ввел ли пользователь название товара.
' Если название введено, обновить запрос и включить
' название в поиск.
if srchProductName <> "" then
sql = sql & "and chrName like '%" & srchProductName & "%'"
end if
Теперь все готово к выполнению команды SQL (см. листинг 12.12). Страница открывает подключение ADO к базе данных и выполняет команду SQL. После этого можно переходить к выводу найденных записей.

Листинг 12.12. OrderSearch.asp (продолжение)
' Create an ADO database connection
set dbOrderSearch = server.createobject("adodb.connection")
' Create the record set
set rsOrderSearch = server.CreateObject("adodb.recordset")
' Open the connection using our ODBC file DSN
dbOrderSearch.open("filedsn=WildWillieCDs")
' Execute our built on the fly query.
set rsOrderSearch = dbOrderSearch.Execute(sql)
%>
<!-- Net we work on the dispaly of the search
results. A table is started to display
the data. -->
<BR><BR>
Далее начинается таблица для вывода найденных заказов (см. листинг 12.13). В ней отображаются все основные параметры заказа, а также информация о состоянии заказа и удобные средства для его изменения.
Листинг 12.13. OrderSearch.asp (продолжение)
<table border="1" cellpadding="3" cellspacing="3">
<!-- Build the header. -->
<tr>
<th>Order ID</th>
<th>Date Ordered</th>
<th>Order Total</th>
<th>Ship to<BR>Last Name</th>
<th>Ship to<BR>Email Address</th>
<th>Bill to<BR>Last Name</th>
<th>Bill to<BR>Email Address</th>
<th>Order Status</th>
<th>Delete</th>
</tr>
!-- Заголовок таблицы. --
В этой точке начинается перебор записей полученного набора (см. листинг 12.14). В первом столбце выводится идентификатор заказа, оформленный в виде ссылки для получения подробной информации о заказе.
Листинг 12.14. OrderSearch.asp (продолжение)
<%
' Loop through the returned results.
do until rsOrderSearch.EOF
%>
<!-- Start a results row. -->
<tr>
<td align="center">
<!-- A link is built on the order id to give
the user a link to the order details. -->
<a href="OrderDetail.asp?idOrder=<%=rsOrderSearch("idOrder")%>&
idShopper=<%=rsOrderSearch("idShopper")%>">
<%=rsOrderSearch("idOrder")%>
</a>
</td>
В листинге 12.15 выводится дата оформления заказа и его итоговая стоимость. Дальше выводится фамилия и адрес электронной почты, указанные в реквизитах доставки. Адрес связывается с функцией mailto:, чтобы при щелчке на нем можно было отправить сообщение по электронной почте. Также в таблице выводится фамилия и адрес электронной почты, указанные в реквизитах выписки счета.
Листинг 12.15. OrderSearch.asp (продолжение)
<!-- Next we display the date of the order, the order
total and the shipping last name. -->
<td align="center"><%=rsOrderSearch("dtOrdered")%></td>
<td align="center"><%=formatcurrency(rsOrderSearch("intTotal")/100, 2)%></td>
<td align="center"><%=rsOrderSearch("chrShipLastName")%></td>

<td align="center">
<!-- Next the shipping email address is displayed
and it built as a link so an email can be
easily sent. -->
<a href="mailto:<%=rsOrderSearch("chrShipEmail")%>">
<%=rsOrderSearch("chrShipEmail")%></a>
</td>

<!-- Show the billing last name. -->
<td align="center"><%=rsOrderSearch("chrBillLastName")%></td>
<td align="center">
<!-- Next the billing email address is displayed
and it built as a link so an email can be
easily sent. -->
<a href="mailto:<%=rsOrderSearch("chrBillEmail")%>">
<%=rsOrderSearch("chrBillEmail")%></a>
</td>
Переходим к выводу текущего состояния заказа (см. листинг 12.16). В нашем примере определено четыре разных состояния. Мы построим список, в котором будет выводиться текущее состояние. Список находится на форме, позволяющей легко выбрать новое состояние.
Прежде всего мы получаем текущее состояние и присваиваем значение одной из переменных, обеспечивающих выбор этого состояния по умолчанию в списке.
Листинг 12.16. OrderSearch.asp (продолжение)
<td>
<%

stat0 = ""
stat1 = ""
stat2 = ""
stat3 = ""

' Check the status of the order. A check is
' done to build a defaulted selected variable
' so the current shipping status is defaulted.
select case rsOrderSearch("idStage")
' Case 0 is that the order has been retrieved.
case 0
Stat0 = "Selected"

' Case 1 is that the order is fulfilled and ready
' for shipping.
case 1
Stat1 = "Selected"

' Case 2 indicates the order has been shipped and we
' display the shipping number.
case 2
Stat2 = "Selected"

' If none of these are set then we indicate that
' customer service should be called.
case 3
Stat3 = "Selected"

end select
%>
В листинге 12.17 создается форма, которая передает обновленную информацию о состоянии заказа странице UpdateStatus.asp. На форме создается скрытое поле, в котором сохраняется идентификатор заказа. По содержимому этого скрытого поля страница UpdateStatus.asp определяет то, состояние какого заказа ей следует обновить.
Листинг 12.17. OrderSearch.asp (продолжение)
<!-- A form is built to update the
order status. -->
<form method="post" action="UpdateStatus.asp">

<!-- In order to know what form will be updated, a
hidden variable is stored with the order id. -->
<input type="hidden" name="intOrder"
value="<%=rsOrderSearch("idOrder")%>">
В листинге 12.18 на форме создается список, содержащий все допустимые состояния заказа. Вставка переменных в теги OPTION обеспечивает выбор в списке текущего состояния заказа.
Листинг 12.18. OrderSearch.asp (продолжение)
<!-- A slect box is created with the different order
status variables. Note the default selected
variables are utilized in each option. And,
the shipping number is shown if the status
is shipped.-->
<select name="intStage">
<option value="0" <%=Stat0%>>Order Received and to be Processed
<option value="1" <%=Stat1%>>Order Fulfilled and Ready to be Shipped
<option value="2" <%=Stat2%>>Order Shipped -
<%=rsOrderSearch("chrShippingNum")%>
<option value="3" <%=Stat3%>>Call Customer Service for Assistance
</select><BR>
Если заказ был отправлен покупателю, необходимо предусмотреть возможность ввода номера транспортной накладной. Для этого в таблице создается специальное текстовое поле. После этого создается кнопка Submit, и построение формы завершается.
Листинг 12.19. OrderSearch.asp (продолжение)
<!-- An input element is created so the shipping number can
be entered. -->
<input type="text" value="<%=rsOrderSearch("chrShippingNum")%>"
name="chrShippingNum">

<!-- Submit button for the form. -->
<input type="Submit" value="Update" name="Submit"></form></td>
В листинге 12.20 создается ссылка для удаления заказа из системы. Ссылка связывается со страницей DeleteOrder.asp, идентификатор заказа передается в URL. Затем мы переходим к следующей записи и продолжаем вывод результатов. С завершением цикла завершается работа страницы.
Листинг 12.20. OrderSearch.asp (продолжение)
<td>
<!-- Build a link to delete teh order from
the database. -->
<a href="DeleteOrder.asp?idOrder=<%=rsOrderSearch("idOrder")%>">
Delete</a>
</td>
</tr>
<%
' Move to the next row.
rsOrderSearch.MoveNext
Loop
%>
</table>
</body></html>
Перейдем к тестированию нового поискового интерфейса.Начнем с простого поиска всех заказов в системе (не забудьте создать примеры заказов в базе данных).
Заказы в базе данных. Таким образом, для выборки заказов вообще не обязательно вводить какие-либо критерии. Для каждого заказа выводятся все основные данные, включая текущее состояние заказа. Идентификатор заказа в левом столбце связывается со ссылкой, при помощи которой можно получить дополнительную информацию.
Теперь попробуем выполнить более специфичный поиск. Введите определенный интервал даты и итоговой суммы (проследите за тем, чтобы по крайней мере один заказ в базе соответствовал обоим критериям).
Результаты поиска. Обратите внимание: даты и итоговые суммы всех найденных заказов принадлежат заданным интервалам.
Удаление и изменение состояния заказов
От поиска и фильтрации перейдем к основным операциям с заказами: удалению и изменению состояния.
Сначала рассмотрим процедуру удаления заказов. Как говорилось выше, идентификатор заказа передается странице в составе URL В листинге 12.21 страница открывает подключение ADO к базе данных, после чего создает запрос SQL для вызова хранимой процедуры sp_DeleteOrder, передавая ей идентификатор заказа. После выполнения запроса пользователь возвращается на страницу поиска заказов.
СОВЕТ
Возможно, пользователя было бы логичнее вернуть на страницу результатов поиска, однако удаленный заказ к этому моменту станет недействительным. Одно из возможных решений заключается в том, чтобы сохранить только что созданный запрос SQL в сеансовой переменной и выполнить его заново без повторного создания.

Листинг 12.21. DeleteOrder.asp
<%@ Language=VBScript %>
<%
' ****************************************************
' DeleteOrder.asp - удаление заказа из базы данных.
' ****************************************************
' Create an ADO database connection
set dbDeleteOrder = server.createobject("adodb.connection")
' Create the record set
set rsDeleteOrder = server.CreateObject("adodb.recordset")
' Open the connection using our ODBC file DSN
dbDeleteOrder.open("filedsn=WildWillieCDs")
' Call the sp_DeleteOrder stored procedure to
' delete the specified order from the database.
sql = "execute sp_DeleteOrder " & request("idOrder")
' Execute the statement
set rsDeleteOrder = dbDeleteOrder.Execute(sql)
Response.Redirect "OrderSearch.asp"
%>
Хранимая процедура sp_DeleteOrder предназначена для удаления заказа из базы данных. Не забывайте, что информация удаляется не только из таблицы OrderData - сведения о заказе также необходимо удалить из таблиц PaymentData, OrderStatus, Basket и BasketItem.
Сначала хранимая процедура определяет идентификатор корзины, по которому удаляются записи из других таблиц. После этого выполняются соответствующие команды SQL DELETE (см. листинг 12.22).
Листинг 12.22. Хранимая процедура sp_DeleteOrder
CREATE PROCEDURE sp_DeleteOrder
@idOrder int
AS
declare @idBasket int
select @idBasket = idBasket from OrderData where
idOrder = @idOrder
delete from orderdata where idOrder = @idOrder
delete from paymentdata where idOrder = @idOrder
delete from OrderStatus where idOrder = @idOrder
delete from Basket where idBasket = @idBasket
delete from BasketItem where idBasket = @idBasket
Перейдем к изменению состояния заказов. Для решения этой задачи необходимы три параметра: идентификатор заказа, передаваемый в скрытом поле, идентификатор нового состояния, и номер транспортной накладной (если он имеется).
Страница вызывает хранимую процедуру sp_UpdateOrderStatus и передает ей три параметра. После обновления состояния заказа пользователь возвращается на страницу поиска заказов.
Листинг 12.23. UpdateStatus.asp
<%@ Language=VBScript %>
<%
' ****************************************************
' UpdateStatus.asp - Handles updating the order status
' for the specified order.
' ****************************************************
' Create an ADO database connection
set dbUpdateStatus = server.createobject("adodb.connection")
' Create the record set
set rsUpdateStatus = server.CreateObject("adodb.recordset")
' Open the connection using our ODBC file DSN
dbUpdateStatus.open("filedsn=WildWillieCDs")
' Retrieve the order it, order stage
' and shipping number
intOrder = request("intOrder")
intStage = request("intStage")
chrShippingNum = request("chrShippingNum")
' Build the sql statement and call the
' sp_UpdateOrderStatus stored procedure
sql = "execute sp_UpdateOrderStatus " & _
intOrder & ", " & _
intStage & ", '" & _
chrShippingNum & "'"
' Execute the statement
set rsUpdateStatus = dbUpdateStatus.Execute(sql)
' Send the user back to the order search
Response.Redirect "OrderSearch.asp"
%>
Текущее состояние заказа обновляется хранимой процедурой sp_UpdateOrderStatus (см. листинг 12.24). В качестве параметров передается идентификатор заказа, код состояния и номер транспортной накладной. Процедура обновляет текущие данные командой SQL UPDATE. Как говорилось выше, запись состояния создается в таблице OrderStatus при оформлении заказа покупателем.

Листинг 12.24. Хранимая процедура sp_UpdateOrderStatus
CREATE PROCEDURE sp_UpdateOrderStatus
@idOrder int,
@intStage int,
@chrShippingNum varchar(100)
AS
update OrderStatus set
idStage = @intStage,
chrShippingNum = @chrShippingNum
where
idOrder = @idORder
Давайте посмотрим, как работают средства обновления состояния заказов. Измените состояние первого заказа на "Обратитесь в службу поддержки за помощью" ("Call Customer Service for Assistance") и нажмите кнопку Update.
С писок после обновления - обратите внимание на изменившееся состояние первого заказа. Изменения также отражаются в сведениях о состоянии заказа, получаемых пользователем при загрузке профиля.
Просмотр и редактирование заказов
На следующем этапе мы построим страницу вывода подробной информации о заказе. Внешне она похожа на аналогичную страницу, на которой выводилась подробная информация о заказе для покупателя. Но на этот раз пользователю необходимо предоставить средства для обновления заказа при возможных изменениях. Начало страницы OrderDetail.asp приводится в листинге 12.25.
Как и все остальные управляющие страницы, она начинается с включения заголовочных файлов для проверки пользователя и построения панели ссылок.
Листинг 12.25. OrderDetail.asp
<%@ Language=VBScript %>
<!-- #Include file="include/validatecheck.asp" -->
<HTML>
<!--
OrderDetail.asp - Displays the detail on the order
and allows for the key fields to be updated.
-->
<body>
<!-- #include file="include/navinclude.asp" -->
Переходим к получению данных заказа (см. листинг 12.26). Этот процесс начинается с выполнения хранимой процедуры sp_RetrieveReceiptHeader, загружающей данные заголовка.
Листинг 12.26. OrderDetail.asp (продолжение)
<%
' Create an ADO database connection
set dbOrderReceiptHeader = server.createobject("adodb.connection")
set rsOrderReceiptHeader = server.CreateObject("adodb.recordset")

' Open the connection using our ODBC file DSN
dbOrderReceiptHeader.open("filedsn=WildWillieCDs")
' Call the stored procedure to retrieve the
' receipt header.
sql = "execute sp_RetrieveReceiptHeader " & _
Request("idShopper") & ", " & _
Request("idOrder")
' Execute the SQL statement
set rsOrderReceiptHeader = dbOrderReceiptHeader.execute(sql)
%>
Далее начинается форма, которая передает обновленную информацию странице UpdateOrder.asp (см. листинг 12.27). Затем начинается таблица для вывода адресной информации и сведений о заказе.
Листинг 12.27. OrderDetail.asp (продолжение)
<!-- Форма редактирования данных заказа. -->
<form method="post" action="UpdateOrder.asp">
<!-- Таблица для вывода заголовка -->
<table>
<!-- Идентификатор и дата оформления заказа -->
Идентификатор заказа, разумеется, только отображается; ведь пользователь не может редактировать его, поскольку идентификатор является уникальным признаком заказа. Мы создаем несколько скрытых полей, используемых для идентификации записи в базе данных. В них сохраняются идентификаторы заказа, покупателя и корзины. После скрытых полей выводится дата оформления заказа. Она также не может редактироваться пользователем (см. листинг 12.28).
Листинг 12.28. OrderDetail.asp (продолжение)
<tr>
<td><B>
Order # <%=rsOrderReceiptHeader("idOrder")%></b>

<!-- Several hidden variables are built in so we
can easily update by the key fields for each
table. -->
<input type="hidden" name="idOrder" value="<%=request("idOrder")%>">
<input type="hidden" name="idShopper" value="<%=request("idShopper")%>">
<input type="hidden" name="idBasket" value="<%=rsOrderReceiptHeader("idBasket")%>">
</td>
<td width="75"></td>
<td><b>Order Date: <%=rsOrderReceiptHeader("dtOrdered")%></b></td>
<tr>
<!-- Blank column -->
<tr>
<td colspan="3">&nbsp;</td>
</tr>
Затем мы переходим к выводу адресов для выписки счета и доставки (см. листинг 12.29). На этот раз вся информация выводится в текстовых полях - пользователю необходимо предоставить возможность редактирования данных.
Листинг 12.29. OrderDetail.asp (продолжение)
<!-- Bill to and Ship to header -->
<tr>
<td><b>Bill To:</b></td>
<td width="75"></td>
<td><b>Ship To:</b></td>
<tr>
<!-- Shipping and Billing information -->
<tr>
<td>
<input type="text" name="chrBillFirstName"
value="<% = rsOrderReceiptHeader("chrBillFirstName")%>">
<input type="text" name="chrBillLastName"
value="<% = rsOrderReceiptHeader("chrBillLastName")%>">
</td>
<td width="75"></td>
<td>

<input type="text" name="chrShipFirstName"
value="<% = rsOrderReceiptHeader("chrShipFirstName")%>">

<input type="text" name="chrShipLastName"
value="<% = rsOrderReceiptHeader("chrShipLastName")%>">

</td>
<tr>
<!-- Billing and shipping address. -->
<tr>
<td>
<input type="text" name="chrBillAddress"
value="<% = rsOrderReceiptHeader("chrBillAddress")%>">
</td>
<td width="75"></td>
<td>
<input type="text" name="chrShipAddress"
value="<%=rsOrderReceiptHeader("chrShipAddress")%>">
</td>
<tr>
<!-- Billing and shipping address. -->
<tr>
<td>
<input type="text" name="chrBillCity"
value="<% = rsOrderReceiptHeader("chrBillCity")%>">,
<input type="text" name="chrBillState"
value="<% = rsOrderReceiptHeader("chrBillState")%>" size="2">
<input type="text" name="chrBillZipCode"
value="<% = rsOrderReceiptHeader("chrBillZipCode")%>" size="10">

</td>

<td width="75"></td>

<td>
<input type="text" name="chrShipCity"
value="<% = rsOrderReceiptHeader("chrShipCity")%>">,
<input type="text" name="chrShipState"
value="<% = rsOrderReceiptHeader("chrShipState")%>" size="2">
<input type="text" name="chrShipZipCode"
value="<% = rsOrderReceiptHeader("chrShipZipCode")%>" size="10">
</td>
<tr>
<!-- Billing and shipping phone. -->
<tr>
<td>
<input type="text" name="chrBillPhone"
value="<% = rsOrderReceiptHeader("chrBillPhone")%>">
</td>
<td width="75"></td>
<td>
<input type="text" name="chrShipPhone"
value="<% = rsOrderReceiptHeader("chrShipPhone")%>">
</td>
<tr>
<!-- Billing and shipping email. -->
<tr>
<td>
<input type="text" name="chrBillEmail"
value="<% = rsOrderReceiptHeader("chrBillEmail")%>" size="35">
</td>
<td width="75"></td>
<td>
<input type="text" name="chrShipEmail"
value="<% = rsOrderReceiptHeader("chrShipEmail")%>" size="35">
</td>
<tr>
</table>
После адресов и сведений о заказах выводятся платежные реквизиты (см. листинг 12.30). Обратите внимание: эта информация не включается в сведения о заказе, выводимые для покупателя.
Загрузка платежных реквизитов выполняется хранимой процедурой sp_RetrievePaymentData, которой при вызове передается идентификатор заказа.
Листинг 12.30. OrderDetail.asp (продолжение)
<!-- Display teh payment data . -->
<BR><BR>
<b>Payment Data:</b>
<BR>
<%
' Create an ADO database connection
set dbPaymentData = server.createobject("adodb.connection")
set rsPaymentData = server.CreateObject("adodb.recordset")

' Open the connection using our ODBC file DSN
dbPaymentData.open("filedsn=WildWillieCDs")
' Call the stored procedure to retrieve the
' payment data on the order.
sql = "execute sp_RetrievePaymentData " & _
Request("idOrder")
' Execute the SQL statement
set rsPaymentData = dbPaymentData.execute(sql)
%>
Для вывода платежных реквизитов создается новая таблица (см. листинг 12.31). В ней выводится имя владельца, номер и тип кредитной карты, а также срок ее действия. Вся эта информация может редактироваться пользователем.
Листинг 12.31. OrderDetail.asp (продолжение)
<!-- A table is created to dispaly the payment
data. -->
<table cellpadding="3" cellspacing="3">
<tr>
<!-- Dispaly the card name -->
<td align="right">Card Name:</td>
<td>
<input type="text" name="chrCardName"
value="<%=rsPaymentData("chrCardName")%>">
</td>
<!-- Display the card number -->
<td align="right">Card Number:</td>
<td>
<input type="text" name="chrCardNumber"
value="<%=rsPaymentData("chrCardNumber")%>">
</td>
</tr>
<tr>
<!-- Display the card type. -->
<td align="right">Card Type:</td>
<td>
<input type="text" name="chrCardType" value="<%=rsPaymentData("chrCardType")%>">
</td>
<!-- Display the card expiration date -->
<td align="right">Card Expiration Date:</td>
<td>
<input type="text" name="chrExpDate"
value="<%=rsPaymentData("chrExpDate")%>">
</td>
</tr>
</table>
После платежных реквизитов выводится перечень товаров, входящих в заказ (см. листинг 12.32). Для получения всего содержимого корзины используется хранимая процедура sp_RetrieveReceiptItems. В качестве параметров процедуре передаются идентификаторы покупателя и заказа.
Листинг 12.32. OrderDetail.asp (продолжение)
<%
' Create an ADO database connection
set dbOrderReceiptItems = server.createobject("adodb.connection")
set rsOrderReceiptItems = server.CreateObject("adodb.recordset")

' Open the connection using our ODBC file DSN
dbOrderReceiptItems.open("filedsn=WildWillieCDs")
' SQL statement to retrieve the items orders.
sql = "execute sp_RetrieveReceiptItems " & _
Request("idShopper") & ", " & _
Request("idOrder")
' Execute the SQL statement
set rsOrderReceiptItems = dbOrderReceiptItems.execute(sql)
%>
Для вывода полученных данных создается таблица (см. листинг 12.33). Выводится идентификатор товара, название, атрибуты, количество, цена и стоимость позиции корзины. Все эти поля могут редактироваться пользователем.
Листинг 12.33. OrderDetail.asp (продолжение)
<!-- Build the basket table -->
<table border="0" cellpadding="3" cellspacing="2" width="750">
<tr><td colspan="6"><HR></td></tr>
<!-- Build the header row -->
<tr>
<th>Item Code</th>
<th>Name</th>
<th>Attributes</th>
<th>Quantity</th>
<th>Price</th>
<th>Total</th>
</tr>
В листинге 12.34 начинается цикл перебора всех позиций заказа. Для каждого информационного объекта в таблице создается текстовое поле. Трудность заключается в том, чтобы присвоить каждому текстовому полю уникальное имя.
Проблема решается объединением имени поля (например, chrName) с идентификатором текущего товара. Например, полю названия товара с кодом 99 присваивается имя chrName99. Это позволит нам прочитать уникальные значения на странице UpdateOrder.asp и соответствующим образом обновить содержимое базы данных.
Обратите внимание - редактирование атрибутов товара разрешается лишь в том случае, если у товара ранее были заданы атрибуты. Кроме того, из заказа нельзя исключать позиции, но в них можно устанавливать нулевое количество единиц товара, что приводит к тому же эффекту.
Листинг 12.34. OrderDetail.asp (продолжение)
<%
' Loop through the basket items.
do until rsOrderReceiptItems.EOF
%>
<!-- Show the row -->
<tr>
<!-- Show the product id -->
<td align="center">
<input type="hidden" name="idBasketItem<% = rsOrderReceiptItems("idProduct")%>"
value="<% = rsOrderReceiptItems("idBasketItem")%>">
<input type="text" name="<% = rsOrderReceiptItems("idProduct")%>"
value="<% = rsOrderReceiptItems("idProduct")%>" size="3">
</td>

<!-- Show the product name -->
<td>
<input type="text" name="chrName<% = rsOrderReceiptItems("idProduct")%>"
value="<% = rsOrderReceiptItems("chrName")%>">
</td>

<!-- Show the product attributes -->
<td>
<% if rsOrderReceiptItems("chrColor") <> " " then %>

<input type="text" name="chrSize<% = rsOrderReceiptItems("idProduct")%>"
value="<% = rsOrderReceiptItems("chrSize")%>" size="7">,

<input type="text" name="chrColor<% = rsOrderReceiptItems("idProduct")%>"
value="<% = rsOrderReceiptItems("chrColor")%>" size="7">

<% end if %>
</td>

<!-- Show the product quantity -->
<td align="center">
<input type="text" name="intQuantity<% = rsOrderReceiptItems("idProduct")%>"
value="<%=rsOrderReceiptItems("intQuantity")%>" size="4">
<%'=rsOrderReceiptItems("basketitem.intQuantity")%>
</td>

<!-- Show the product price -->
<td>
<input type="text" name="intPrice<% = rsOrderReceiptItems("idProduct")%>"
value="<%=formatcurrency(rsOrderReceiptItems("intPrice")/100, 2)%>"
size="7">
</td>

<!-- Show the product total cost -->
<td align="right"><%Response.write _
formatcurrency(rsOrderReceiptItems("intPrice")/100 * rsOrderReceiptItems("intQuantity"), 2)%>
</td>
</tr>
<%
' Move to the next row
rsOrderReceiptItems.MoveNext
loop
%>
После содержимого корзины выводится общая стоимость, налог, стоимость доставки и итоговая стоимость. Все эти показатели не редактируются пользователем напрямую, но обновляются при внесении изменений в базу данных.
Листинг 12.35. OrderDetail.asp (продолжение)
<!-- Build a break -->
<tr>
<td colspan="6"><HR></td>
</tr>
<!-- Show the sub total of the basket -->
<tr>
<td colspan="5" align="right"><b>Subtotal:</b></td>
<td align="right"><%Response.Write _
formatcurrency(rsOrderReceiptHeader("intSubtotal")/100, 2) %></td>
</tr>
<!-- Show the shipping total of the basket -->
<tr>
<td colspan="5" align="right"><b>Shipping:</b></td>
<td align="right"><%Response.Write _
formatcurrency(rsOrderReceiptHeader("intShipping")/100, 2) %></td>
</tr>
<!-- Show the tax total of the basket -->
<tr>
<td colspan="5" align="right"><b>Tax:</b></td>
<td align="right"><%Response.Write _
formatcurrency(rsOrderReceiptHeader("intTax")/100, 2) %></td>
</tr>
<!-- Show the total of the basket -->
<tr>
<td colspan="5" align="right"><b>Total:</b></td>
<td align="right"><%Response.Write _
formatcurrency(rsOrderReceiptHeader("intTotal")/100, 2) %></td>
</tr>
Как показано в листинге 12.36, страница завершается кнопкой отправки данных формы и закрывающими тегами страницы.
Листинг 12.36. OrderDetail.asp (продолжение)
<!-- Submit button to process the updates. -->
<tr>
<td colspan="6">
<input type="Submit" value="Submit Changes" name="Submit">
</td>
<tr>
</table>
</form>
</BODY>
</HTML>
В работе страницы используется несколько хранимых процедур. Первая, sp_RetrieveReceiptHeader, загружает данные из таблиц OrderData и Basket и позволяет вывести основные сведения о заказе (см. листинг 12.37).
Листинг 12.37. Хранимая процедура sp_RetrieveReceiptHeader
/* Чтение данных заголовка отчета по идентификаторам покупателя и заказа */
CREATE PROCEDURE sp_RetrieveReceiptHeader
/* При вызове процедуре передаются идентификаторы покупателя и заказа */
@idShopper int,
@idOrder int
AS
/* Получить основную информацию о заказе посредством объединения таблиц OrderData и Basket */
select * from OrderData, Basket
where Orderdata.idOrder = @idOrder and
OrderData.idShopper = @idShopper and
OrderData.idBasket = Basket.idBasket
Хранимая процедура sp_RetrievePaymentData (см. листинг 12.38) загружает платежные реквизиты, относящиеся к заказу. В сущности, она просто возвращает запись с заданным идентификатором заказа.

Листинг 12.38. Хранимая процедура sp_RetrievePaymentData
CREATE PROCEDURE sp_RetrievePaymentData
@idOrder int
AS
select * from paymentdata
where idOrder = @idOrder
Наконец, хранимая процедура sp_RetrieveReceiptItems читает информацию о товарах, заказанных пользователем. Поиск осуществляется по идентификаторам заказа и покупателя.
Листинг 12.39. Хранимая процедура sp_RetrieveReceiptItems
/* Stored Procedure to retrieve the receipt items. */
CREATE PROCEDURE sp_RetrieveReceiptItems
/* Pass in the ID of the shopper and the Id of the order */
@idShopper int,
@idOrder int
AS
/* Select the contents of the basketitem, basket and orderdata tables. */
select * from basketitem, orderdata
where orderdata.idshopper = @idShopper and
orderdata.idOrder = @idOrder and
basketitem.idbasket = orderdata.idbasket
ПРИМЕЧАНИЕ
На странице OrderDetail.asp пользователю предоставляется полная свобода действий. Он может ввести абсолютно любое название, идентификатор товара и т.д. Вероятно, выбор пользователя следует ограничить значениями из заранее заполненных списков.

От вывода заказа и подготовки его к редактированию мы переходим к обработке внесенных изменений. В листинге 12.40 приведено начало страницы UpdateOrder.asp, предназначенной для обработки всех изменений на странице редактирования заказов.
Страница открывает подключение ADO к базе данных, после чего читает основные сведения о заказе - идентификатор заказа, идентификатор покупателя и идентификатор корзины.
Листинг 12.40. UpdateOrder.asp
<%@ Language=VBScript %>
<%
' ****************************************************
' UpdateOrder.asp - Handles updating the order data
' posted from the order detail page.
' ****************************************************
' Create an ADO database connection
set dbOrderUpdate = server.createobject("adodb.connection")
set rsOrderUpdate = server.CreateObject("adodb.recordset")

' Open the connection using our ODBC file DSN
dbOrderUpdate.open("filedsn=WildWillieCDs")
' Retrieve our three key values, the id of the order
' the id of the shopper and the id of the basket for
' the order.
idOrder = request("idOrder")
idShopper = request("idShopper")
idBasket = request("idBasket")
Затем из базы данных загружаются реквизиты выписки счета и доставки. Как обычно, одиночные апострофы в текстовых полях необходимо удвоить (см. листинг 12.41).
Листинг 12.41. UpdateOrder.asp (продолжение)
' Next we retrieve the core order data which
' includes the billing address and shipping
' address. Note that the key fields are updated
' to ensure any single quotes are doubled.
chrBillFirstName = replace(request("chrBillFirstName"), "'", "''")
chrBillLastname = replace(request("chrBillLastName"), "'", "''")
chrShipFirstName = replace(Request("chrShipFirstName"), "'", "''")
chrShipLastname = replace(request("chrShipLastName"), "'", "''")
chrBillAddress = replace(request("chrBillAddress"), "'", "''")
chrShipAddress = replace(request("chrShipAddress"), "'", "''")
chrBillCity = replace(request("chrBillCity"), "'", "''")
chrBillState = request("chrBillState")
chrBillZipCode = request("chrBillZipCode")
chrShipCity = replace(request("chrShipCity"), "'", "''")
chrShipState = request("chrShipState")
chrShipZipCode = request("chrShipZipCode")
chrBillPhone = request("chrBillPhone")
chrShipPhone = request("chrShipPhone")
chrBillEmail = request("chrBillEmail")
chrShipEmail = request("chrShipEmail")
Основные данные заказа обновляются хранимой процедурой sp_UpdateOrderData. Процедура получает всю адресную информацию и обновляет таблицу OrderData (см. листинг 12.42).
Листинг 12.42. UpdateOrder.asp (продолжение)
' The order data is updated by calling
' the sp_UpdateOrderData stored procedure
sql = "execute sp_UpdateOrderData " & _
idOrder & ", '" & _
chrBillFirstName & "', '" & _
chrBillLastname & "', '" & _
chrBillAddress & "', '" & _
chrBillCity & "', '" & _
chrBillState & "', '" & _
chrBillZipCode & "', '" & _
chrBillPhone & "', '" & _
chrBillEmail & "', '" & _
chrShipFirstName & "', '" & _
chrShipLastname & "', '" & _
chrShipAddress & "', '" & _
chrShipCity & "', '" & _
chrShipState & "', '" & _
chrShipZipCode & "', '" & _
chrShipPhone & "', '" & _
chrShipEmail & "'"
' Execute the SQL statement
set rsOrderUpdate = dbOrderUpdate.execute(sql)
Переходим к обработке платежных реквизитов (см. листинг 12.43). Мы получаем их значения со страницы OrderDetail.asp, как обычно, удваиваем одиночные апострофы. Затем хранимая процедура sp_UpdatePayment вносит изменения в базу данных.
Листинг 12.43. UpdateOrder.asp (продолжение)
' Next we are going to update the
' payment data. Each of the payment
' data fields are retrieved. Note that
' we check for single quotes in key
' fields.
chrCardName = replace(request("chrCardName"), "'", "''")
chrCardNumber = request("chrCardNumber")
chrCardType = request("chrCardType")
chrExpDate = request("chrExpDate")
' Build the SQL statement to update the
' payement data.
sql = "execute sp_UpdatePaymentData " & _
idOrder & ", '" & _
chrCardType & "', '" & _
chrCardNumber & "', '" & _
chrExpDate & "', '" & _
chrCardName & "'"
' Now execute the SQL statement
set rsOrderUpdate = dbOrderUpdate.execute(sql)
Все готово к внесению изменений в базу данных. Вспомните: для построения имен полей использовалась комбинация постоянного имени и идентификатора товара. Чтобы построить эти имена заново, необходимо загрузить текущий список товаров, входящих в заказ. Для получения списка используется хранимая процедура sp_RetrieveReceiptHeader (см. листинг 12.44).
Листинг 12.44. UpdateOrder.asp (продолжение)
' Создать объект подключения к базе данных
set dbOrderReceiptItems = server.createobject("adodb.connection")
set rsOrderReceiptItems = server.CreateObject("adodb.recordset")

' Открыть подключение, используя файловый DSN ODBC
dbOrderReceiptItems.open("filedsn=WildWillieCDs")
' Построить команду вызова хранимой процедуры для загрузки
' содержимого заказа.
sql = "execute sp_RetrieveReceiptItems " & _
Request("idShopper") & ", " & _
Request("idOrder")
' Выполнить команду SQL
set rsOrderReceiptItems = dbOrderReceiptItems.execute(sql)
Получив набор записей, мы перебираем их и генерируем имена полей, по которым мы будем обращаться к их содержимому. Для этого идентификатор товара объединяется с именем поля (см. листинг 12.45).
Листинг 12.45. UpdateOrder.asp (продолжение)
' To read the input fields for each basket item,
' we are going to have to loop through the
' basket items again. Then that item can
' be updated.
do until rsOrderReceiptItems.EOF
' Retrieve the product id. That will be utilized
' to build the name of the HTML input fields
' from the posting page.
idProduct = rsOrderReceiptItems("idProduct")

' The name of each basket item field is built with
' the id of the product tacked onto the end.
idBasketItem = request("idBasketItem" & idProduct)
chrName = replace(request("chrName" & idProduct), "'", "''")
chrColor = request("chrColor" & idProduct)
chrSize = request("chrSize" & idProduct)
intQuantity = cint(request("intQuantity" & idProduct))
intPrice = request("intPrice" & idProduct) * 100
При каждой итерации пересчитывается общая стоимость заказа и количество единиц заказанного товара, после чего позиция корзины обновляется при помощи хранимой процедуры sp_UpdateBasketItem (см. листинг 12.46).
Листинг 12.46. UpdateOrder.asp (продолжение)
' При каждой итерации общая стоимость корзины
' увеличивается на стоимость текущей позиции.
subtotal = subtotal + (intPrice * intQuantity)

' При каждой итерации общее количество единиц товара
' увеличивается на количество единиц в текущей позиции.
TotalQuantity = TotalQuantity + intQuantity
' Построить команду вызова хранимой процедуры
' для обновления позиции корзины.
sql = "execute sp_UpdateBasketItem " & _
idBasketItem & ", '" & _
chrName & "', '" & _
chrColor & "', '" & _
chrSize & "', " & _
intQuantity & ", " & _
intPrice

' Выполнить команду SQL
set rsOrderUpdate = dbOrderUpdate.execute(sql)

' Перейти к следующей записи
rsOrderReceiptItems.MoveNext
' Вернуться к началу цикла Loop
Loop
Последняя операция - обновление итоговой стоимости заказа - приведена в листинге 12.47. Для ее проведения необходимо пересчитать налог и стоимость доставки. При этом будет использоваться объект COM ECStoreBizLogiс, созданный нами в главе 8.
Страница создает экземпляр этого объекта и вызывает функции Shipping и Tax для пересчета стоимости доставки и налога. При вызове функции Shipping передается общее количество заказанных единиц товара, а при вызове функции Tax - общая стоимость корзины.
Листинг 12.47. UpdateOrder.asp (продолжение)
' Create the Bussiness Logic component to
' calculate the tax and shipping.
set BizLogic = server.CreateObject("ECStoreBizLogic.TaxShip")
' Call the shipping function of our component. The quantity
' is passed in and must be in a long data type format. The
' Shipping fee is returned.
Shipping = BizLogic.Shipping(cLng(TotalQuantity))
' Calculate the tax by calling the Tax function of
' our component. We pass in the shipping state and the
' order subtotal. The value is also stored in a session
' variable.
Tax = BizLogic.tax(cstr(chrShipState), clng(subtotal))
Зная общую стоимость, налог и стоимость доставки, можно вычислить итоговую стоимость заказа. Хранимая процедура sp_UpdateBasket обновляет соответствующие параметры корзины. После этого пользователь направляется на страницу OrderDetail.asp для просмотра изменений (см. листинг 12.48).
Листинг 12.48. UpdateOrder.asp (продолжение)
' Calculate teh new total.
Total = subtotal + shipping + tax
' Build a SQL statement to update the basket data
sql = "execute sp_UpdateBasket " & _
idBasket & ", " & _
TotalQuantity & ", " & _
SubTotal & ", " & _
Shipping & ", " & _
Tax & ", " & _
Total & ", 1"

' Execute the SQL statement
set rsOrderUpdate = dbOrderUpdate.execute(sql)
' Send the user back to the order detail
' page
Response.Redirect "OrderDetail.asp?idOrder=" & idOrder & _
"&idShopper=" & idShopper
%>
При обновлении данных заказа эта страница использует несколько хранимых процедур. Процедура sp_UpdateOrderData обновляет все основные реквизиты доставки и выписки счета в таблице OrderData. При вызове она получает набор параметров и конструирует команду SQL UPDATE (см. листинг 12.49).
Листинг 12.49. Хранимая процедура sp_UpdateOrderData
CREATE PROCEDURE sp_UpdateOrderData
@idOrder int,
@chrBillFirstName varchar(255),
@chrBillLastName varchar(255),
@chrBillAddress varchar(255),
@chrBillCity varchar(255),
@chrBillState varchar(25),
@chrBillZipCode varchar(25),
@chrBillPhone varchar(255),
@chrBillEmail varchar(255),
@chrShipFirstName varchar(255),
@chrShipLastname varchar(255),
@chrShipAddress varchar(255),
@chrShipCity varchar(255),
@chrShipState varchar(25),
@chrShipZipCode varchar(25),
@chrShipPhone varchar(255),
@chrShipEmail varchar(255)
AS
update orderdata set

chrBillFirstName = @chrBillFirstName,
chrBillLastname = @chrBillLastname,
chrBillAddress = @chrBillAddress,
chrBillCity = @chrBillCity,
chrBillState = @chrBillState,
chrBillZipCode = @chrBillZipCode,
chrBillPhone = @chrBillPhone,
chrBillEmail = @chrBillEmail,
chrShipFirstName = @chrShipFirstName,
chrShipLastname = @chrShipLastname,
chrShipAddress = @chrShipAddress,
chrShipCity = @chrShipCity,
chrShipState = @chrShipState,
chrShipZipCode = @chrShipZipCode,
chrShipPhone = @chrShipPhone,
chrShipEmail = @chrShipEmail
where
idOrder = @idOrder
Хранимая процедура sp_UpdatePaymentData обновляет платежные реквизиты заказа (см. листинг 12.50). Она тоже получает набор параметров и строит соответствующую команду SQL UPDATE.
Листинг 12.50. Хранимая процедура sp_UpdatePaymentData
CREATE PROCEDURE sp_UpdatePaymentData
@idOrder int,
@chrCardType varchar(100),
@chrCardNumber varchar(50),
@chrExpDate varchar(25),
@chrCardName varchar(150)
AS
update PaymentData set
chrCardType = @chrCardType,
chrCardNumber = @chrCardNumber,
chrExpDate = @chrExpDate,
chrCardName = @chrCardName
where
idOrder = @idOrder
Хранимая процедура sp_UpdateBasketItem получает параметры, описывающие отдельную позицию корзины, и обновляет ее соответствующим образом (см. листинг 12.51). Обновляемая запись определяется переданным идентификатором позиции.
Листинг 12.51. Хранимая процедура sp_UpdateBasketItem
CREATE PROCEDURE sp_UpdateBasketItem
@idBasketItem int,
@chrName varchar(255),
@chrColor varchar(50),
@chrSize varchar(50),
@intQuantity int,
@intPrice int
AS
update BasketItem set
chrName = @chrName,
chrColor = @chrColor,
chrSize = @chrSize,
intQuantity = @intQuantity,
intPrice = intPrice
where idBasketItem = @idBasketItem
Наконец, хранимая процедура sp_UpdateBasket (см. листинг 12.52) обновляет ключевые поля заданной корзины.
Листинг 12.52. Хранимая процедура sp_UpdateBasket
/* Обновление содержимого корзины */
CREATE PROCEDURE sp_UpdateBasket
/* При вызове процедуре передается идентификатор корзины, количество единиц товара, общая стоимость заказа, стоимость доставки, налог, итоговая стоимость и признак размещения заказа. */
@idBasket int,
@intQuantity int,
@intSubTotal int,
@intShipping int,
@intFreeShipping int,
@intTax int,
@intTotal int,
@intOrderPlaced int
AS
/* Обновление корзины */
update basket set
intQuantity = @intQuantity,
intSubtotal = @intSubtotal,
intShipping = @intShipping,
intFreeShipping = @intFreeShipping, intTax = @intTax,
intTotal = @intTotal,
intOrderPlaced = @intOrderPlaced
where idBasket = @idBasket
Давайте посмотрим, как обновление заказов работает на практике. Обратите внимание: все ключевые поля готовы к редактированию.
Попробуйте изменить количество единиц заказанного товара. Это, в свою очередь, должно отразиться на стоимости позиции, размере налога, стоимости доставки и итоговой стоимости заказа.
Обновленная страница с подробными сведениями о заказе. Обратите внимание: все вычисляемые поля были обновлены правильными величинами.

Итоги
На этом завершается часть книги, посвященная управлению заказами. В действительности мы лишь в общих чертах познакомились с операциями, выполняемыми администратором магазина в полноценном интерфейсе управления.

 

 
На главную | Содержание | < Назад....Вперёд >
С вопросами и предложениями можно обращаться по nicivas@bk.ru. 2013 г. Яндекс.Метрика