Создание нового типа справочника аналитики

Скачать: 

 

Давайте качественно проанализируем предыдущую статью ("Создание простого справочника"). В этой статье мы решили вопросы ведения реестра компьютеров. Но полностью? Понятно, что ПК имеет гораздо больше характеристик, чем мы предвидели. Это и список комплектующих, и подключены к нему периферийные устройства. Комплектующие тоже отличаются своими параметрами.
Очевидно, все эти данные нужно регистрировать в системе.
Для того, чтобы дополнить наш справочник, нам необходимо создать список этих комплектующих. По сути, он уже существует в справочнике номенклатуры. Однако в уже существующих данных необходимо добавить технические характеристики каждого комплектующего. Для этого, нам нужно создать такой справочник аналитики, который бы содержал список комплектующих (взятых из справочника номенклатуры) разбитых на группы и технические характеристики, записанных отдельным списком.
Для реализации этого мы создадим новый тип справочника аналитики.
Созданный на основе этого типа справочник аналитики будет содержать список комплектующих в одной таблице, а их характеристик - в другой.
Отображать на экране мы будем с помощью двух списков. В одном комплектующие, а во втором характеристики, причем при перемещении по списку комплектующих их характеристики будут изменяться автоматически.
Начнем ...
Немножко теории о создании типов справочников аналитики.Типы справочников аналитики сохраняются в папке Scripts / Cls. Для каждого типа создается отдельная папка. Ее название и будет обозначением нового типа. В этой папке могут быть следующие файлы:

  • class.xml - здесь описываются переменные справочника аналитики;

  • dpmapping.xml - здесь эти переменные привязываются к полям таблицы;

  • form.xml - описывается форма для добавления данных в справочник;

  • *. Js - обработчик событий на форме;

  • list.xml - описываются отображения списка;

  • list.js - описываются обработчик событий списка (не обязательно).

Если справочник по строкам, то в эту же папку надо поместить файл *. xml с описанием этого Grid `а и отдельную папку, в которой будут содержаться файлы для обработки данных в этом списке:

  • class.xml - здесь описываются переменные справочника аналитики;
    dpmapping.xml - здесь эти переменные привязываются к полям таблицы;
    form.xml - описывается форма для добавления данных в справочник;

  • *. Js - обработчик событий на форме.

Все просто и понятно. Достаточно внимательно описать переменные и поля, создать справочник аналитики нужного (созданного) типа и смело пользоваться.
Создания таблиц. Как создавать таблицы в существующей базе данных мы знаем. Поэтому здесь я просто приведу названия таблиц и списки полей.
Нам нужна одна таблица, где мы опишем код, название и серийный номер детали. Назовем ее CL_KOMPL. Поля, входят: FKOD, FNAME, FSERNOM.
Во второй нам нужно всего два поля (потом поймем почему так. Эту таблицу назовем CL_KOMPL_ROW. Поля, входят: FPARNAME, FPARZNACH.
Таблицы созданы и к этому больше не будем обращаться. Просто привожу в листинге 1 текст файла для их создания.

Листинг 1

<?xml version="1.0" encoding="UTF-8"?>

<STRU>

<TABLES>

<table attr="" dospath="cdbf" path="cl_mdb" pattern="CL_KOMPL" sys="com" table="CL_KOMPL"></table>

<table attr="" dospath="cdbf" path="cl_mdb" pattern="CL_KOMPL_ROW" sys="com" table="CL_KOMPL_ROW"></table>

</TABLES>

<PATTERNS>

<CL_KOMPL>

<PARENTS>

<PARENT pattern="FWIDPARENT"/>

</PARENTS>

<FIELDS>

<FWID_CL attr=" " type="long"/>

<FKOD attr=" " type="text"/>

<FNAME attr=" " type="text"/>

<FSERNOM attr=" " type="text"/>

<FREM attr=" " type="longtext"/>

</FIELDS>

</CL_KOMPL>

<CL_KOMPL_ROW>

<PARENTS>

<PARENT pattern="FWIDPARENT"/>

</PARENTS>

<FIELDS>

<FWID_CL attr=" " type="long"/>

<FPARNAME attr=" " type="long"/>

<FPARZNACH attr=" " type="text"/>

</FIELDS>

</CL_KOMPL_ROW>

</PATTERNS>

</STRU>

Для создания нового типа справочника выполним следующие действия:
1.В Scripts / Cls создадим папку с именем справочника (например, clkompl.
2.Создадим все необходимые файлы в папке.
Описание типа справочника (class.xml).Итак, поля таблиц созданы, можно описывать класс справочника. Напоминаю, что в классе мы описываем переменные справочника. Имена этим переменным мы будем давать такие, как и имена полей, заменяя первую букву F на H.

Листинг 2

<?xml version="1.0" encoding="UTF-8"?>

<DpCL type="clkompl" name="Комплектуючі|Комплектующие" sys="COM">

<Parents>

<parent classid="cls.CL1"/>

</Parents>

<Header>

<var name="HKOD" datatype="text"/>

<var name="HNAME" datatype="text"/>

<var name="HSERNOM" datatype="text"/>

<var name="HREM" datatype="text"/>

</Header>

<rows>

<row id="KLROWS" classid="KLROWS"/>

</rows>

</DpCL>

 

В листинге 2 не сложно разобраться самостоятельно. Здесь описано текст файла class.xml. Все же дадим некоторые пояснения.
<Header> - Описывает основные переменные справочника. Здесь указывается и тип этой переменной.
<rows> - привязывает к основному классу строки. Classid - идентификатор класса строк. Папку с таким же названием нужно создать в папке Scripts / Cls / название справочника.
Связь переменных с полями таблицы (dpmapping.xml). Теперь "привяжем" сменные справочника к полям таблицы. В системе "Дебет Плюс" это осуществляется с помощью файла dpmapping.xml, описанный в листинге 3.

Листинг 3

<?xml version="1.0" encoding="UTF-8"?>

<DpCL type="clkompl">

<Header>

<Tables>

<table name="CL" />

<table name="CLRELCLCL" ID="FWID_CL" />

<table name="CL_KOMPL" ID="FWID_CL" />

</Tables>

<Fields>

<field name="FWID" table="CL" var="ID" />

<field name="FTXT" table="CL" var="HTXT" />

<field name="FTXTS" table="CL" var="HTXTS" />

<field name="FCOD" table="CLRELCLCL" var="HCOD" />

<field name="FCL" table="CLRELCLCL" var="HCL" />

<field name="FWID_CL" table="CLRELCLCL" var="ID" />

<field name="FWID" table="CL_KOMPL" var="ID" />

<field name="FKOD" table="CL_KOMPL" var="HKOD" />

<field name="FNAME" table="CL_KOMPL" var="HNAME" />

<field name="FSERNOM" table="CL_KOMPL" var="HSERNOM" />

<field name="FREM" table="CL_KOMPL" var="HREM" />

</Fields>

</Header>

<Rows>

<Tables>

<table name="CL_KOMPL_ROW" reffield="FWID_CL"/>

</Tables>

</Rows>

</DpCL>

Здесь name - имя поля, table - имя таблицы, в которой это поле находится, var - имя переменной. Если все понятно - идем дальше.
<Файл list.xml. Как описывать отображения таблицы на экране мы уже знаем. Поэтому просто привожу листинг этого файла:

Листинг 4

<?xml version="1.0" encoding="UTF-8"?>

<list>

<grid>

<field field="kompl.FKOD" text="Код|Код" width="20" />

<field field="kompl.FNAME" text="Назва|Название" width="40" />

<field field="kompl.FSERNOM" text="Серійний номер|Серийный номер" width="20" />

<field field="kompl.FREM" text="Примітка|Примечание" width="70" />

</grid>

</list>

 

В этом коде kompl.FKOD означает <псевдоним таблицы> <название поля>. Такая комбинация образовалась в результате использования функции tie. Эта функция присоединяет к основной таблице другую по выбранным полям. Она используется в файле list.js

Файл list.js.

Листинг 5

function clAfterLoad()

{

this.addTies = clAddTies;

}

 

function clAddTies()

{

this.extTie("CL",Fcl);

this.extTieEx("ext0","fwid","CL","0");

this.subTie("CL_KOMPL", "kompl", "FWID_CL", "Fwid");

}

Функция clAfterLoad () обязательна. В ней описываются методы и свойства таблицы, отображаемой на гриде.
Попробуем объяснить только последнюю строку функции clAddTies (). Здесь:

  • "CL_KOMPL" - имя таблицы, присоединяется.

  • "Kompl" - псевдоним этой таблицы.

  • "FWID_CL", "Fwid" - поля таблиц, по которым эти таблицы объединяются.

Все довольно просто. Если вы создали и этот файл, то можем идти дальше.
Теперь нужно создать форму для заполнения таблицы. Опять же мы это уже с вами делали. Я остановлюсь только на использовании грида.

Файл form.js и form.xml.

Листинг 6

<?xml version="1.0" encoding="utf-8"?>

<Form>

<Controls col="3">

<Label text="№" width="80" gridwidth="1"/>

<TextField ID="FKOD" width="80" gridwidth="2"/>

<Label text="Назва:|Название:" gridwidth="1"/>

<TextField ID="FNAME" width="450" gridwidth="2"/>

<Label text="Серійний номер:|Серийный номер:" gridwidth="1"/>

<TextField ID="FSERNOM" width="450" gridwidth="2"/>

<Label text="Примітка:|Примечание:" gridwidth="1"/>

<TextField ID="FREM" width="450" gridwidth="2"/>

 

<grid ID="grid" width="700" height="250" gridwidth="3" align="fill" valign1="fill"/>

</Controls>

<script languige="JavaScript" src="form.js"/>

</Form>

 

Листинг 7

 

include("objects//DpCl.js");

include("gridedit.js");

 

var sDir = rootDirectory() + "cls/clkompl/";

var sTmpTbl = "TMP_KOMPL_ROW";

var sRowTbl = "CL_KOMPL_ROW";

var sRowClass = "KLROWS";

var objCl = extPar.dpObj;

var ctrlLinker;

var gridTbl;

var oGridEdit;

 

function onLoad()

{

this.onEscape = exit;

Caption(ru("Комплектующие", "Комплектуючі") +": "+ modeName(this.sMode));

ctrlLinker = new DpCtrlLinker(objCl);

FKOD.setMask("######");

FKOD.setFocus();

ctrlLinker.addLink("HKOD", FKOD);

ctrlLinker.addLink("HNAME", FNAME);

ctrlLinker.addLink("HSERNOM", FSERNOM);

ctrlLinker.addLink("HREM", FREM);

ctrlLinker.toControls();

loadGrid(this.sMode);

}

 

function loadGrid(sMode)

{

DropTable(sTmpTbl);

var sSQL = "SELECT * "

+ " INTO " + sTmpTbl

+ " FROM ^"+ sRowTbl;

var sWhere = " WHERE 1<>1 ";

if (sMode != "ADD")

sWhere = " WHERE FWID_CL="+ sqlTo(objCl.getID());

sSQL += sWhere;

ExecuteSQL(sSQL);

gridTbl = OpenTable("m", "SELECT * FROM "+ sTmpTbl);

clTie(gridTbl,"kk","="+250+",FPARNAME");

//browse(gridTbl);

grid.setXMLDir(sDir);

grid.setXMLFile("l_kompllist.xml");

grid.setTable(gridTbl);

grid.build();

grid.setData(sRowClass);

this.gridMenuInit = gridMenuInit;

this.gridMenuRum = gridMenuRum;

grid.loadMenuHandler(this,"gridMenuInit");

grid.selectMenuHandler(this,"gridMenuRum");

 

oGridEdit = new DpGridEdit(grid);

oGridEdit.canEdit = canEditRecord;

oGridEdit.saveRecord = saveRecord;

}

 

 

function saveRecord()

{

var rowID = parseInt(grid.getTable().getValue("fwid"));

var oRow = objCl.getRow(sRowClass, rowID);

if (oRow == null)

{

oRow = objCl.createRow(sRowClass);

oRow.setID(rowID);

objCl.appendRow(sRowClass, oRow);

}

with (oRow)

{

setVar("RPARNAME", gridTbl.getValue("FPARNAME"));

setVar("RPARZNACH", gridTbl.getValue("FPARZNACH"));

}

return true;

}

 

function canEditRecord()

{

return true;

}

 

function gridMenuInit(grid)

{

grid.AddMenuItem("ADD","Додати|Добавить");

if (!grid.getTable().isEmpty())

{

grid.AddMenuItem("EDIT","Редагувати|Редактировать");

grid.AddMenuItem("COPY","Копіювати|Копировать");

grid.AddMenuItem("DEL","Видалити|Удалить");

}

}

 

function gridMenuRum(sID, grid)

{

var tbl = grid.getTable();

var tName = tbl.getTableName();

var rowID = tbl.getValue("FWID");

switch(sID)

{

case "DEL":

var nGridPos = grid.getRowSelected();

ExecuteSQL("delete From "+ tName

+" where Fwid="+ sqlTo(rowID));

objCl.deleteRow(sRowClass, rowID);

tbl.requery();

tbl.setAbsolute(nGridPos-1);

grid.refresh();

break;

case "ADD": case "EDIT": case "COPY":

var oRow;

if(sID == "ADD")

oRow = objCl.createRow(sRowClass);

else if(sID == "EDIT")

oRow = objCl.getRow(sRowClass, rowID);

else if(sID == "COPY")

oRow = objCl.copyRow(sRowClass, rowID);

if(!oRow)

break;

if (!rowEdit(sID, oRow))

break;

tbl.requery();

grid.refresh();

break;

}

return true;

}

 

function onSave()

{

ctrlLinker.toVars();

storeToDb(sRowTbl, sTmpTbl);

exit();

}

 

function rowEdit(sMode, oRow)

{

var par = new Object();

par.dpObj = oRow;

par.mode = sMode;

par.tblName = sTmpTbl;

par.dpObj.hasExt = hasExt;

par.formFile = "cls/"+ objCl.sClassId +"/KLROWS/form.xml";

 

showWindow(par.formFile, "XMLDLG", par);

if(par.escape)

return false;

var id = oRow.getID();

if(inList(sMode, "ADD", "COPY"))

objCl.appendRow(sRowClass, oRow);

obj2DB(id, oRow.jObj, null, sTmpTbl);

return true;

}

 

function hasExt()

{

return false;

}

 

function storeToDb(sTbl, tmpTbl)

{

var sFld = GetPatternIntersection (sTbl, sTbl);

ExecuteSQL("DELETE FROM ^"+ sTbl +" WHERE FWID_CL="+ sqlTo(objCl.getID()));

ExecuteSQL("UPDATE "+ tmpTbl +" SET Fwid_cl="+ sqlTo(objCl.getID()));

ExecuteSQL("INSERT INTO ^"+ sTbl +" ("+ sFld +")"

+" SELECT "+ sFld +" FROM "+ tmpTbl);

}

 

function exit()

{

gridTbl.close();

DropTable(sTmpTbl);

}

 

include("sys/DpBaseDlg.js");

 

Грид загружается на форму и инициализируется функцией loadGrid. Поля на форме привязываются к переменным класса с помощью объекта ctrlLinker. Это дает возможность удобного хранения данных и загрузки данных на форму. Все остальное - это обработка данных. Ищите описание объектов и функций в файлах бизнес-логики системы "Дебет Плюс".
 Один момент. Описания грида, который находится на форме находится в файле l_kompllist.xml. Вот его листинга.

Листинг 8

<?xml version="1.0" encoding="UTF-8"?>

<grid>

<field field="=tcl('CL','TXT',250,FPARNAME)" text="Параметр|Параметр" width="20" />

<field field="FPARZNACH" text="Значення|Значение" width="30" />

</grid>

 

Для успешного выполнения кода необходимо создать справочник аналитики № 250 "Характеристики комплектующих.

Теперь создадим класс для добавления строк. Поскольку мы полностью разработали один класс, то нет проблемы разобраться как сделать другой.
В папке Scripts / Cls / название справочника создадим папку KLROWS. В ней четыре файла. Приводим без комментариев.

class.xml

<?xml version="1.0" encoding="utf-8"?>

<DpCl type="KLROWS">

<Header>

<var name="RWID_CL" datatype="long"/>

<var name="RPARNAME" datatype="text"/>

<var name="RPARZNACH" datatype="text"/>

</Header>

</DpCl>

dpmapping.xml

<?xml version="1.0" encoding="utf-8"?>

<DpCl type="KLROWS">

<Header>

<Tables>

<table name="CL_KOPML_ROWS"/>

</Tables>

<Fields>

<field name="FWID_CL" table="CL_KOMPL_ROWS" var="RWID_CL"/>

<field name="FPARNAME" table="CL_KOPML_ROWS" var="RPARNAME"/>

<field name="FPARZNACH" table="CL_KOPML_ROWS" var="RPARZNACH"/>

</Fields>

</Header>

</DpCl>

form.xml

<?xml version="1.0" encoding="utf-8" ?>

<Form>

<Controls col="4" >

<ComboBox ID="FPARNAME">

<option selected="true" value="-">---</option>

</ComboBox>

<Label text="Значення|Значение"/>

<TextField ID="FPARZNACH" width="130" colspan="2"/>

</Controls>

<script languige="JavaScript" src="form.js"/>

</Form>

 

form.js

include("Objects/DpVal.js");

include("Objects/DpBank.js");

 

var obj = extPar.dpObj;

var oVal;

var ctrlLinker;

 

function onLoad()

{

Caption(ru("Комплектующие", "Комплектуючі")

+ ": " + modeName(extPar.mode));

//Блок для заповнення списку ComboBox з довідника аналітики № 250

var tt = OpenTable("Select a.FCOD,b.FWID,b.FTXT, a.FWID_CL From ^CL b, ^CLRELCLCL a WHERE b.FWID=a.FWID_CL and a.FCL=250 ORDER BY b.FTXT");

for(tt.MoveFirst();!tt.IsEOF();tt.MoveNext())

{

var sVal = tt.getValue("FCOD");

var sTxt = tt.getValue("FTXT");

FPARNAME.addItem(sVal,sTxt);

}

FPARNAME.selectedIndex = obj.getVar("RPARNAME");

//showObject(obj);

//Конец блока

ctrlLinker = new DpCtrlLinker(obj);

ctrlLinker.addLink("RPARNAME", FPARNAME);

ctrlLinker.addLink("RPARZNACH", FPARZNACH);

ctrlLinker.updateData(false);

}

 

function onSave()

{

ctrlLinker.updateData(true);

}

 

function hasExt()

{

// return false;

}

 

include("sys\\DpBaseDlg.js");

 

 

Теперь добавим справочник аналитики созданного типа и вот, что у нас получилось: