Цель: При переводе заказа в состояние Оплаченный
необходимо проверять, может ли быть товар выписан, и если да, то вычитать необходимое количество товара.
Примечание: для простоты будем считать, что товар может находиться на разных складах, и затребованное количество ищется по всем складам, суммируя.
Бизнес-сервер – это специализированный класс, который позволяет перехватить реально выполняемые сервисом данных операции над источником данных (такие как создание записи в таблице базы данных, удаление, обновление) в зависимости от состояния объекта данных. Для реализации такого класса есть стереотип businessserver
.
Нпример, для реализации проверки наличия товара на складе в момент сохранения заказа со статусом Оплаченный
, необходимо:
1.Добавить на диаграмму классов класс со стереотипом businessserver
.
2.Сохранить диаграмму, в свойствах класса Заказ
указать соответствующее имя бизнес-сервера и сохранить форму редактирования класса. Затем, из появившегося выпадающего списка, выбрать срабатывание на OnAllEvents
(т.е. при любых операциях сервиса данных):
3.Сохранить диаграмму. Сгенерировать бизнес-серверы и объекты данных.
4.Проект с бизнес-серверами добавить в Solution
. Добавить ссылку на проект с бизнес-сервером в проекты приложений.
5.После этого прописать в скобках программиста следующие строчки (для выбора вариантов используется сочетание Ctrl
+Пробел):
// *** Start programmer edit section *** (Using statements)
using System.Collections;
using ICSSoft.STORMNET;
using ICSSoft.STORMNET.FunctionalLanguage;
using ICSSoft.STORMNET.FunctionalLanguage.SQLWhere;
// *** End programmer edit section *** (Using statements)
6.Далее в коде бизнес-сервера обработать всё следующим образом:
public virtual ICSSoft.STORMNET.DataObject[] OnUpdateЗаказ(АСУ_Склад.Заказ UpdatedObject)
{
// *** Start programmer edit section *** (OnUpdateЗаказ)
// Определим массив, который будем возвращать для обновления.
DataObject[] ret = new DataObject[0];
// Проверим на то, что пришедший объект - это именно то, что нам нужно (создан или изменён и статус установлен в Оплачено).
if ((UpdatedObject.GetStatus() == ICSSoft.STORMNET.ObjectStatus.Created || UpdatedObject.GetStatus() == ICSSoft.STORMNET.ObjectStatus.Altered) && Array.IndexOf(UpdatedObject.GetAlteredPropertyNames(), "Статус") >= 0 && UpdatedObject.Статус == СостояниеЗаказа.Оплаченный)
{
// Построим ограничение и вычитаем все объекты ТоварНаСкладе, которые нам подходят.
Заказ заказ = UpdatedObject;
ICSSoft.STORMNET.FunctionalLanguage.Function lf = null;
for (int i = 0; i < заказ.СтрокаЗаказа.Count; i++)
{
if (lf != null)
{
if (заказ.СтрокаЗаказа[i].Товар != null)
lf = FunctionBuilder.BuildOr(
lf,
FunctionBuilder.BuildEquals<ТоварНаСкладе>(x => x.Goods, заказ.СтрокаЗаказа[i].Товар));
}
else
{
if (заказ.СтрокаЗаказа[i].Товар != null)
lf = FunctionBuilder.BuildEquals<ТоварНаСкладе>(x => x.Goods, заказ.СтрокаЗаказа[i].Товар);
}
}
ICSSoft.STORMNET.Business.LoadingCustomizationStruct lcs = ICSSoft.STORMNET.Business.LoadingCustomizationStruct.GetSimpleStruct(typeof(ТоварНаСкладе),"ТоварНаСкладеE");
lcs.LimitFunction = lf;
ICSSoft.STORMNET.DataObject[] objs = ICSSoft.STORMNET.Business.DataServiceProvider.DataService.LoadObjects(lcs);
// Разместим вычитанные объекты в отсортированном списке для удобного доступа в дальнейшем.
System.Collections.SortedList sl = new System.Collections.SortedList();
for (int i = 0; i < objs.Length; i++)
{
if (sl.ContainsKey(((ТоварНаСкладе)objs[i]).Товар.__PrimaryKey))
{
((System.Collections.ArrayList)sl[objs[i].__PrimaryKey]).Add(objs[i]);
}
else
{
System.Collections.ArrayList списокТоваров = new System.Collections.ArrayList();
списокТоваров.Add(objs[i]);
sl.Add(((ТоварНаСкладе)objs[i]).Товар.__PrimaryKey, списокТоваров);
}
}
// Определим строчку для сообщения об ошибке.
string errStr = string.Empty;
ArrayList retObjs = new ArrayList();
// Проверим наличие товара на складах, если не хватает, то выдадим сообщение об ошибке, если хватает, то вычитаем количество.
for (int i = 0; i < заказ.СтрокаЗаказа.Count; i++)
{
if (sl.ContainsKey(заказ.СтрокаЗаказа[i].Товар.__PrimaryKey))
{
ArrayList arl = ((System.Collections.ArrayList)sl[заказ.СтрокаЗаказа[i].Товар.__PrimaryKey]);
int количествоНаСкладах = 0; for (int j = 0; j < arl.Count; j++)
{
количествоНаСкладах +=
((ТоварНаСкладе)arl[j]).Количество;
}
if (количествоНаСкладах <
заказ.СтрокаЗаказа[i].Количество)
{
errStr += " Не хватает товара \"" + заказ.СтрокаЗаказа[i].Товар.Название + "\" в наличии: " + количествоНаСкладах + ", требуется " + заказ.СтрокаЗаказа[i].Количество + Environment.NewLine;
}
else
{
int колич = заказ.СтрокаЗаказа[i].Количество;
for (int j = 0; j < arl.Count; j++)
{
if (колич > 0 &&
((ТоварНаСкладе)arl[j]).Количество > колич)
{
((ТоварНаСкладе)arl[j]).Количество -= колич;
колич = 0; retObjs.Add(arl[j]);
}
else
{
if (колич > 0)
{
колич -= ((ТоварНаСкладе)arl[j]).Количество;
((ТоварНаСкладе)arl[j]).Количество = 0;
retObjs.Add(arl[j]);
}
}
}
}
}
else
{
errStr += "Товар \"" +
заказ.СтрокаЗаказа[i].Товар.Название + "\" в наличии отсутствует." + Environment.NewLine;
}
}
// В случае, если чего-то не хватило, сообщаем об этом пользователю.
if (errStr != string.Empty)
{
throw new Exception(errStr);
}
// Если всё нормально, то возвращаем массив объектов, которые надо обновить.
ret = new DataObject[retObjs.Count]; retObjs.CopyTo(ret, 0);
}
return ret;
// *** End programmer edit section *** (OnUpdateЗаказ)
}