Пример программирования web-сервиса на VIP Назад В начало Вперед

Приведенный ниже пример предоставляет web-клиентам список названий имеющихся матценностей. Список матценностей хранится в таблице KatMc.

Goods.vih

#include ISetData.vih
#include IModify.vih
#component 'CGoods'

//************************************************************

web objInterface IGoods;

  property al_date : date; // atl_lastDate, atl_lastTime и atl_lastUser
  property al_time : time; // нужны для того, что бы отслеживать
  property al_user : comp; // пассивные блокировки в doSetData

  property id   : comp;   // это на самом деле NRec
  property name : string; // ограничимся наименованием

  // атрибут primary у индекса заставит web-сервисы 
  // позиционироваться по Id перед вызовом DoSetData
  index byId = id(unique, primary); 
end;

//************************************************************

web vipInterface VGoods implements ISetData, IGetHandle, IGoods, IModify;
public:
  // конструктор по умолчанию
  constructor Init;

  // конструктор экземпляра
  constructor InitId(cId : comp);

  function  ISetData.DoSetData(owner : ObjRef; positionExist : boolean) : longInt;
end;

Goods.vip

#include Goods.vih
#component 'CGoods'

//************************************************************

interface vGoods;

var prev_date : date;  // в этих переменных сохраняем		 
var prev_time : time;  // значения для последующего сравнения 
var prev_user : comp;  // в doSetData						 

// переменная нужна для реализации ISetData.modification
var l_modification : boolean;

// переменная нужна для реализации конструктора экземпляра InitId
var l_id : comp;

//------------------------------------------------------------

create view 

as select *

from
  KatMc

// понадобится когда будет использоваться конструктор экземпляра
bounds byId = l_id == KatMc.NRec
;

//------------------------------------------------------------

property ISetData.modification : boolean absolute l_modification;

property IGoods.name	: string absolute KatMc.Name;
property IGoods.id	: comp   absolute KatMc.NRec;
property IGoods.al_date : date read KatMc.atl_lastDate 
							 write prev_date := result;
property IGoods.al_time : time read KatMc.atl_lastTime
							 write prev_time := result;
property IGoods.al_user : comp read KatMc.atl_lastUser
							 write prev_user := result;
index IGoods.byId auto;

//------------------------------------------------------------

procedure IGetHandle.CreateHandle;
{
  SetIfcHandleConstructorName('InitId');
  AddIfcHandleParameter(l_Id);
}

//------------------------------------------------------------

procedure ISetData.OpenTransaction;
{
  BeginTransaction(0);
  // поскольку OpenTransation вызывается только для заглавного объекта
  // нужно выставить modification в true, что бы DoSetData знала, что делать
  modification := true;
}

//------------------------------------------------------------

// сюда нам приходит код возврата, который мы вернем из DoSetData
procedure ISetData.CloseTransaction (rCode : longInt); 
{
  if( rCode = tsOk )
	EndTransaction
  else
	AbortTransaction;

  // делаем как было
  modification := false;
}

//------------------------------------------------------------

function ISetData.DoSetData (owner : ObjRef; positionExist : boolean) : longint;
{
 // переменная l_modification выставляется в true в OpenTransaction для головного
 // объекта, или того подобъекта, который мы модифицируем.
 // Такая реализация позволяет использовать один и тот же объект как головной,
 // модифицируя его, так и как подобъект (ссылка) другого объекта.

  if (l_modification)
  {
	// Это наша внутренняя договоренность, если id = 0, то insert, иначе update
	if (id = 0)
	result := DoInsert; // вызываем стандарный insert
	else
	if (  prev_date = KatMc.atl_lastDate // так проверяем
		and prev_time = KatMc.atl_lastTime // пассивные блокировки
		and prev_user = KatMc.atl_lastUser)

		if (positionExist)
		result := DoUpdate; // вызываем стандарный update
		else
		result := tsInvalidPositioning; // уже удалили

	else
		result := tsConflict; // уже изменили

	// Это нужно, если был использован конструктор экземпляра,
	// или в нашем примере для работы createHandle
	if (result = tsOk)
	l_id := id; 
  }

  // Если есть primary key - запись найдется автоматически, иначе можно искать 
  // по какому-либо полю. Либо по договоренности (например наименование) 
  // либо по тому, которое <> '' или 0, тогда можно будет указывать любой 
  // уникальный атрибут, не зная id
  else 
  {
	result := 0;
	if (not positionExist) id := 0; // лучше пусть будет нулевая ссылка, чем кривая
  }
}

//------------------------------------------------------------

constructor InitId( cId : comp );
{
 l_id := cId;
 pushBounds(tbbyId);
 result := true;
}

//------------------------------------------------------------

constructor Init;
{
 id := 0;
 result := true;
}

//------------------------------------------------------------

function IModify.DoInsert : word;
{
  result := insert current KatMc;
}

//------------------------------------------------------------

function IModify.DoUpdate : word;
{
  result := update current KatMc;
}

//------------------------------------------------------------

function IModify.DoDelete : word;
{
   result := delete current KatMc;
}

//------------------------------------------------------------

implementation IModify.DoFlush abstract; 

end.