Въвеждането на информацията за изработеното от работниците трябва да се извършва своевременно и това може да се осъществи, както с интерактивните средства на модул Производство, така и чрез разработените Web services в Colibri® ERP, свързани с модула за производство.
Използването на web seрvices позволява контрол на аутентикацията и пълна автоматизация на комуникацията между Colibri® ERP и необходимата в случая външна софтуерна система за събиране и натрупване на данните за изработеното от работниците.
Информацията в тази глава е предназначена основно за разработчиците на web services за комуникация с производствения модул на Colibri® ERP.
Процесът е следния:
Информацията за изработеното от работниците се събира от външна система за електронно регистриране на изработеното;
Външната система периодично подава събраната за изработеното информация към Colibri® ERP чрез web service;
Colibri® ERP приема информацията, проверява я за коректност и връща отговор към външната система с информация за приетите данни и информация за откритите грешни записи или несъответствия.
Основната структура от данни, която е необходимо да се подава от външната система е последователност от записи всеки от които е масив със спедните полета:
array( "idOperPersCard" => array("name" => "idOperPersCard", "type" => "xsd:integer") , "CNum" => array("name" => "CNum", "type" => "xsd:string") , "idOper" => array("name" => "idOper", "type" => "xsd:integer") , "ONum" => array("name" => "ONum", "type" => "xsd:string") , "idSector" => array("name" => "idSector", "type" => "xsd:integer") , "SectorNum" => array("name" => "SectorNum", "type" => "xsd:string") , "idRecipe" => array("name" => "idRecipe", "type" => "xsd:integer") , "ExecOrder" => array("name" => "ExecOrder", "type" => "xsd:integer") , "RefNum" => array("name" => "RefNum", "type" => "xsd:string") , "QuantityOK" => array("name" => "QuantityOK", "type" => "xsd:double") , "QuantityWaste" => array("name" => "QuantityWaste", "type" => "xsd:double") , "QuantityWasteSubj" => array("name" => "QuantityWasteSubj", "type" => "xsd:double") , "CompleteTime" => array("name" => "CompleteTime", "type" => "xsd:string") , "QuantityPlan" => array("name" => "QuantityPlan", "type" => "xsd:double") , "QuantityProd" => array("name" => "QuantityProd", "type" => "xsd:double") , "QuantityBr" => array("name" => "QuantityBr", "type" => "xsd:double") , "toDo" => array("name" => "toDo", "type" => "xsd:double") , "Note" => array("name" => "Note", "type" => "xsd:string") , "idOperCard" => array("name" => "idOperCard", "type" => "xsd:integer") )
Показаната структура съдържа информация и за типа на всяко от полетата.
Задължителни полета са:
idOperCard – Вътрешен уникален номер на операция за изпълнение от ПК в Colibri® ERP, за която операция се подава заработка;
RefNum – референтен номер на изпълнителя, работника. В списъка с работниците съответства на полето Код. Това е общ референтен номер по-който Colibri® ERP и външната система разпознават един и същи работник;
QuantitiOK – брой изпълнения на операция Onum в SectorNum от работника RefNum, отговарящи на критериите за качество;
QuantityWaste - брой изпълнения на операция Onum в SectorNum от работника RefNum, завършили с брак не по вина на работника;
QuantityWasteSubj - брой изпълнения на операция Onum в SectorNum от работника RefNum, завършили с брак по вина на работника;
CompleteTime – време на подаване на операцията, съдържащо дата и час. Тази информация е текст със следния формат „DD.MM.YYYY hh:mm:ss”.
Ето един примерен масив в запитване за изпращане на заработки (PHP код):
$work[] = array( "idOperPersCard" => "" , "idOperCard" => "12378" , "RefNum" => "10002" , "QuantityOK" => "100" , "QuantityWaste" => "" , "QuantityWasteSubj" => "" , "CompleteTime" => "25.03.2020 17:56:21" );
Тази е основната функция и е предназначена да импортира заработки от друга система.
Добре е всяка ПК да е с една рецепта (макар да не е задължително, но така се улеснява проверата в последствие, ако е необходимо)! Това е нормален случай, когато ПК е и маршрутна карта за производството на дадени изделия. В данните лисва номера на рецептата и заработката ще се въведе във всички рецепти от ПК (с номер CNum), в чиито списък с операции и работни центрове присъстват тези от импортирания запис.
Идентификацията се извършва по idOperCard, RefNum.
Функцията работи по следния начин:
Първо се проверяват за коректност всички данни;
Ако някой запис не е добре конфигуриран, не се обработва никой от записите;
Ако всички данни са добре конфигурирани, и тогава се вмъкват в съответната ПК, като се използва уникалния идентификационен номер idOperCard;
Ако някоя ПК (CNum) е приключена, записът за нея се прескача и не се обработва.
Детайлно, работата на функцията е разгледана по-нататък.
Функция за автоматизирано въвеждане и обновяване на списъка с работници от външната система към Colibri® ERP. Структурата на подаваните от външната система данни е следната:
array( "idPersonal" => array("name" => "idPersonal", "type" => "xsd:integer") , "PersNum" => array("name" => "PersNum", "type" => "xsd:string") , "RefNum" => array("name" => "RefNum", "type" => "xsd:string") , "PersName" => array("name" => "PersName", "type" => "xsd:string") , "isActive" => array("name" => "isActive", "type" => "xsd:integer") )
Задължителни полета са:
RefNum – референтен номер на изпълнителя, работника. В списъка с работниците в Colibri® ERP, съответства на полето Код. Това е общ рефернтен номер по-който Colibri® ERP и външната система разпознават един и същи работник;
PersName – име на работника или служителя;
isActive – поле, показващо дали работника ще е активен или не от гледна точка на Colibri® ERP. Стойност 1 за активен, 0 – за неактивен.
Ето един примерен масив в PHP код, който може да бъде подаван от външна система, за да се допълва или модифицира списъка с персонала в Colibri® ERP:
$workman[] = array( "RefNum" => "YYYYY" , "PersName" => "Харалампи Хаджипокарахаралампиев" , "isActive" => "1" );
Ако в списъка с персонала на Colibri® ERP липсва човек с RefNum, посочен в записа, то се добавя нов работник в този списък.
Ако в списъка с персонала на Colibri® ERP вече има човек с RefNum, посочен в записа, се модифицират неговото име в съответствие с PersName, а неговата активност спрямо Colibri® ERP в съответствие със стойността на isActive.
Функцията връща масив от записи, съдържащи данните за наличните в Colibri® ERP операции от списъка с операции, заедно със съответния работен център (сектор).
Структурата на получавания масив е следната:
array( "idOper" => array("name" => "idOper", "type" => "xsd:integer") , "idSector" => array("name" => "idSector", "type" => "xsd:integer") , "ONum" => array("name" => "ONum", "type" => "xsd:string") , "OName" => array("name" => "OName", "type" => "xsd:string") , "SectorNum" => array("name" => "SectorNum", "type" => "xsd:string") , "SectorName" => array("name" => "SectorName", "type" => "xsd:string") )
Където:
ONum - номер на операцията в списъка с операции в Colibri® ERP;
OName – наименование на операцията;
SectorNum – номер на сектор, на който се изпълнява операция ONum;
SectorName – наименование на сектора.
Ето и пример за отговор от Colibri® ERP - масив с данни за операция и сектор:
0 => array ( 'idOper' => 68, 'idSector' => 13, 'ONum' => 'ШЛ', 'OName' => 'Шлайфане', 'SectorNum' => 'У-Ш', 'SectorName' => 'Участък- шлайфане', ), ......... )
Примерен код на PHP извикване на функция GetOperations:
<?php include("nusoap.php"); // Entry point data $WS_URL = "https://dev3.edabg.com/erp/ws/wsbase.php?wsdl"; // Initializing client $sc = new nusoap_client($WS_URL, true); $err = $sc->getError(); if ($err) { echo "Constructor error $err\n"; } $sc->soap_defencoding = "UTF-8"; $sc->decode_utf8 = false; $sc->data_encoding = "UTF-8"; $sc->encode_utf8 = false; // Login използвайки потребител soap който е от тип web service $result = $sc->call("erpSOAPServer..Login", array("username" => "soap", "password" => "123")); echo "Calling ...<br>"; //------------------------------------------------------ // Test for function $result = $sc->call("erpSOAPProd..GetOperations", //------------------------------------------------------ $result = $sc->call("erpSOAPProd..GetOperations"); if ($sc->fault) { echo "Fault:<br>"; echo "<pre>".var_export($result,true)."</pre>"; } else { $err = $sc->getError(); if ($err) { echo "Error: $err<br>"; } else { echo "<pre>".var_export($result,true)."</pre>"; } } //------------------------------------------------------ // End of Test for function $result = $sc->call("erpSOAPProd..GetOperations", //------------------------------------------------------ echo "<hr>Request<br>"; echo "<pre>"._h(var_export($sc->request,true))."</pre>"; echo "<hr>Response<br>"; echo "<pre>"._h(var_export($sc->response,true))."</pre>"; $result = $sc->call("erpSOAPServer..Logout"); ?>
Този web service е предназначен да предаде на външна система за електронно събиране на заработките, списък от тройки ПК-операция-сектор (CNum-ONum-SectorNum), за да бъдат използвани при натрупването на информация за изпълнение по тях.
Функцията връща масив от записи, съдържащи данните за използваните в момента (в производствени карти) операции, заедно със съответния им работен център (сектор). Това са тройки ПК-операция-сектор, които са за производствени карти, които не са приключени.
Структурата на данните, които връща функцията е следната:
array( "OrderNum" => array("name" => "OrderNum", "type" => "xsd:string") , "OrderDate" => array("name" => "OrderDate", "type" => "xsd:dateTime") , "OrderName" => array("name" => "OrderName", "type" => "xsd:string") , "CNum" => array("name" => "CNum", "type" => "xsd:string") , "CDate" => array("name" => "CDate", "type" => "xsd:dateTime") , "CName" => array("name" => "CName", "type" => "xsd:string") , "idRecipe" => array("name" => "idRecipe", "type" => "xsd:integer") , "RNum" => array("name" => "RNum", "type" => "xsd:string") , "RName" => array("name" => "RName", "type" => "xsd:string") , "MNum" => array("name" => "MNum", "type" => "xsd:string") , "MName" => array("name" => "MName", "type" => "xsd:string") , "idOperCard" => array("name" => "idOperCard", "type" => "xsd:integer") , "idOper" => array("name" => "idOper", "type" => "xsd:integer") , "ONum" => array("name" => "ONum", "type" => "xsd:string") , "OName" => array("name" => "OName", "type" => "xsd:string") , "idSector" => array("name" => "idSector", "type" => "xsd:integer") , "SectorNum" => array("name" => "SectorNum", "type" => "xsd:string") , "SectorName" => array("name" => "SectorName", "type" => "xsd:string") , "toDo_max" => array("name" => "toDo_max", "type" => "xsd:double") , "toDo" => array("name" => "toDo", "type" => "xsd:double") , "QuantityOK" => array("name" => "QuantityOK", "type" => "xsd:double") , "QuantityWaste" => array("name" => "QuantityWaste", "type" => "xsd:double") , "QuantityWasteSubj" => array("name" => "QuantityWasteSubj", "type" => "xsd:double") )
Където имаме:
Данни за поръчката за производство;
"OrderNum" => array("name" => "OrderNum", "type" => "xsd:string") , "OrderDate" => array("name" => "OrderDate", "type" => "xsd:dateTime") , "OrderName" => array("name" => "OrderName", "type" => "xsd:string")
Данни за производствената карта;
, "CNum" => array("name" => "CNum", "type" => "xsd:string") , "CDate" => array("name" => "CDate", "type" => "xsd:dateTime") , "CName" => array("name" => "CName", "type" => "xsd:string")
Данни за рецептата:
, "idRecipe" => array("name" => "idRecipe", "type" => "xsd:integer") , "RNum" => array("name" => "RNum", "type" => "xsd:string") , "RName" => array("name" => "RName", "type" => "xsd:string")
Данни за произвеждания продукт:
, "MNum" => array("name" => "MNum", "type" => "xsd:string") , "MName" => array("name" => "MName", "type" => "xsd:string")
Идентификационен уникален номер на операцията в производствена карта:
, "idOperCard" => array("name" => "idOperCard", "type" => "xsd:integer")
Данни за производствената операция и работния център:
, "idOper" => array("name" => "idOper", "type" => "xsd:integer") , "ONum" => array("name" => "ONum", "type" => "xsd:string") , "OName" => array("name" => "OName", "type" => "xsd:string") , "idSector" => array("name" => "idSector", "type" => "xsd:integer") , "SectorNum" => array("name" => "SectorNum", "type" => "xsd:string") , "SectorName" => array("name" => "SectorName", "type" => "xsd:string")
В отговора, полетата toDo_max и toDo, показват (в момента на изпълнение на функцията GetActiveOpers), какво количество е планирано да се произведе по операцията и какво количество системата очаква да се изработи по дадена тройка ПК-операция-Сектор, т.е. колко броя детайли стоят пред дадена операция от даден маршрут (ПК), за да бъдат изпълнени.
По този начин върнатата стойност в полетата toDo_max и toDo може да се използва за контрол на регистрираното от работниците изпълнение във външната система за електронно отчитане на изработеното.
toDo_max (= QtyPlan-QtyBrak-QtyOk) - показва максимално възможния брой изпълнения, които да могат да се регистрират по операцията в дадения маршрут (ПК). Полето е предназначено да се използва за контрол от външната система, ако функцията PutWork се изпълнява през известни интервали от време, например през час или в края на деня, т.е. когато информацията за изработеното идва към Colibri® ERP асинхронно спрямо реалната регистрация на изработки във външната система;
toDo – показва точно колко изделия стоят пред операцията, според регистрираното от последното изпълнение на функцията PutWork. Стойността може да се използва от външни системи за регистриране на заработки, които синхронно подават информацията за изработеното към Colibri® ERP, т.е. веднага след регистрирането й от работника. Нормално toDo е по-малко или равно на toDo_max.
И накрая, количествени данни за производствената операция и работния център в момента на изпълнение на сървиса: Данни за производствената операция и работния център:
, "QuantityOK" => array("name" => "QuantityOK", "type" => "xsd:double") , "QuantityWaste" => array("name" => "QuantityWaste", "type" => "xsd:double") , "QuantityWasteSubj" => array("name" => "QuantityWasteSubj", "type" => "xsd:double")
Функциите GetActiveOpers, PutWork трябва да се изпъняват в този ред – циклично – (GetActiveOpers, PutWork); (GetActiveOpers, PutWork),...
След всяко изпълнение на PutWork се променят бройките за изпълнение за тройките ПК-операция-Сектор и последващото изпълнение на GetActiveOpers ще върне нови стойности за полетата toDo_max и toDo.
Всичко по детайлите на извикване на функцията GetActiveOpers е аналогично на функцията GetOperations.
Данните от GetActiveOpers могат да бъдат използвани от външна система за анализ на завършеността или въобще за анализ на актуалното състояние в проиводтвото.
Тук ще разгледаме пример за интерактивност между външна система за събиране на изработеното и въвеждането на информацията от нея в модул Производство на Colibri® ERP.
Нека имаме за даденост следната ПК, т.е. маршрут за производство:
Заработките по тази ПК ще бъдат вкарани автоматично с web service. По-надолу следват описания на запитването и отговора при изпълнението на този web service.
Примерен код за въвеждане на изпълнение от външна система изглежда по следния начин (PHP):
<?php include("../params.inc.php"); //include(PATH_INCLUDE."auth.inc.php"); //include(PATH_INCLUDE."basepage.inc.php"); include("nusoap.php"); // Entry point data $WS_URL = "https://dev3.edabg.com/erp/ws/wsbase.php?wsdl"; // Initializing client $sc = new nusoap_client($WS_URL, true); $err = $sc->getError(); if ($err) { echo "Constructor error $err\n"; } $sc->soap_defencoding = "UTF-8"; $sc->decode_utf8 = false; $sc->data_encoding = "UTF-8"; $sc->encode_utf8 = false; // Login използвайки потребител soap който е от тип web service $result = $sc->call("erpSOAPServer..Login", array("username" => "soap", "password" => "123")); echo "Calling ...<br>"; //------------------------------------------------------ // Test for function $result = $sc->call("erpSOAPProd..PutWork", //------------------------------------------------------ $work[] = array( "idOperPersCard" => "" , "idOperCard" => "12378" , "RefNum" => "10002" , "QuantityOK" => "100" , "QuantityWaste" => "" , "QuantityWasteSubj" => "" , "CompleteTime" => "25.03.2020 17:56:21" ); $work[] = array( "idOperPersCard" => "" , "idOperCard" => "12378" , "RefNum" => "00005" , "QuantityOK" => "1" , "QuantityWaste" => "" , "QuantityWasteSubj" => "" , "CompleteTime" => "11.01.2018 16:05:05" ); $work[] = array( "idOperPersCard" => "" , "idOperCard" => "12379" , "RefNum" => "00005" , "QuantityOK" => "3" , "QuantityWaste" => "" , "QuantityWasteSubj" => "" , "CompleteTime" => "11.01.2018 16:05:10" ); $work[] = array( "idOperPersCard" => "" , "idOperCard" => "12380" , "RefNum" => "00005" , "QuantityOK" => "1" , "QuantityWaste" => "" , "QuantityWasteSubj" => "" , "CompleteTime" => "11.01.2018 16:05:15" ); $work[] = array( "idOperPersCard" => "" , "idOperCard" => "12382" , "RefNum" => "00005" , "QuantityOK" => "1" , "QuantityWaste" => "" , "QuantityWasteSubj" => "" , "CompleteTime" => "11.01.2018 16:05:20" ); $work[] = array( "idOperPersCard" => "" , "idOperCard" => "12383" , "RefNum" => "00005" , "QuantityOK" => "3" , "QuantityWaste" => "" , "QuantityWasteSubj" => "" , "CompleteTime" => "11.01.2018 16:05:25" ); $work[] = array( "idOperPersCard" => "" , "idOperCard" => "12385" , "RefNum" => "00005" , "QuantityOK" => "3" , "QuantityWaste" => "" , "QuantityWasteSubj" => "" , "CompleteTime" => "11.01.2018 16:05:30" ); $work[] = array( "idOperPersCard" => "" , "idOperCard" => "12386" , "RefNum" => "00005" , "QuantityOK" => "2" , "QuantityWaste" => "" , "QuantityWasteSubj" => "" , "CompleteTime" => "11.01.2018 16:05:35" ); $result = $sc->call("erpSOAPProd..PutWork", array($work)); if ($sc->fault) { echo "Fault:<br>"; echo "<pre>".var_export($result,true)."</pre>"; } else { $err = $sc->getError(); if ($err) { echo "Error: $err<br>"; } else { echo "<pre>".var_export($result,true)."</pre>"; } } //------------------------------------------------------ // End of Test for function $result = $sc->call("erpSOAPProd..PutWork", //------------------------------------------------------ echo "<hr>Request<br>"; echo "<pre>"._h(var_export($sc->request,true))."</pre>"; echo "<hr>Response<br>"; echo "<pre>"._h(var_export($sc->response,true))."</pre>"; $result = $sc->call("erpSOAPServer..Logout"); ?>
При извикването на функцията PutWork с горепосочения идентификационен уникален код на операциите idOperCard, след тест за коректност на изпратените данни, се записват всички изпратени заработки. idOperCard се получава от изпълнението на предшестващия сървис GetActiveOpers.
Подаването на записите не изисква специална подредба. Функцията PutWork подрежда записите според реда на изпълнение, зададен в рецептата от съответната ПК и по времето на изпълнение (CompleteTime). Затова е необходимо всяка ПК да се разглежда като маршрутна карта за производство по една рецептура. След сортирането по ред на изпълнение следва сортиране по час на изпълнение – CompleteTime. Така записите за една и съща двойка операция-сектор (ONum-SectorNum) се подреждат и по време на изпълнение.
Нека да обърнем внимание на операция ONum = П-002 от кода. За нея има три записа за общо количество 5 изпълнения, т.е. изпратени са 5 изпълнения, въпреки, че по ПК е зададено да се изпълнят 3. Това е ситуация, при която се прави опит за преизпълнение и системата в отговора си връща информация за това несъответствие.
Резултатът в Colibri® ERP след изпълнение на запитването е следния:
Всички записи в таба Изпълнение на ПК съответстват точно на изпратената чрез разглеждания web service информация. Информацията е приета от Colibri® ERP и вече е обработена по съответния начин в ПК.
Ето как изглежда изпълнението по маршрута на разглежданата ПК:
Преизпълнението на операция с номер П-002 се вижда с отрицателното количество за изпълнение (-2).
Какво ще се предприеме нататък е въпрос на вътрешна организация във фирмата, но може да се открие къде е направено преизпълнение, да се коригира съответния запис или записи и отново да се изпълни запитването, за да се въведат заработките отново.
Функцията PutWork, която е в основата на разглеждания web service връща отговор на всяко запитване. Отговорът може да съдържа:
всички обработени без грешки записи допълнени с информационни полета toDo и Note;
toDo показва колко пъти остава да се изпълни операцията, след като е въведено текущото изпълнение;
Note = ‘OK’ когато изпълнението е въведено без да се нарушават изискванията за коректност. Иначе това поле съдържа информация за възможно несъответствие, която да е в помощ при обработката му;
Съобщения за грешно подадена или лисваща информация в данните;
Ето как изглежда основната част от отговора на разглежданото в нашия пример запитване:
Calling ... array ( 0 => array ( 'idOperPersCard' => 1342, 'RefNum' => '00005', 'QuantityOK' => 3, 'QuantityWaste' => 0, 'QuantityWasteSubj' => 0, 'CompleteTime' => '11.01.2018 16:05:25', 'toDo' => 0, 'Note' => 'OK', ), 1 => array ( 'idOperPersCard' => 1342, 'RefNum' => '00005', 'QuantityOK' => 1, 'QuantityWaste' => 0, 'QuantityWasteSubj' => 0, 'CompleteTime' => '11.01.2018 16:05:05', 'toDo' => 2, 'Note' => 'OK', ), 2 => array ( 'idOperPersCard' => 1342, 'RefNum' => '00005', 'QuantityOK' => 1, 'QuantityWaste' => 0, 'QuantityWasteSubj' => 0, 'CompleteTime' => '11.01.2018 16:05:20', 'toDo' => 1, 'Note' => 'OK', ), 3 => array ( 'idOperPersCard' => 1342, 'RefNum' => '00005', 'QuantityOK' => 3, 'QuantityWaste' => 0, 'QuantityWasteSubj' => 0, 'CompleteTime' => '11.01.2018 16:05:30', 'toDo' => -2, 'Note' => 'ПРЕДУПРЕЖДЕНИЕ! След обработка на записа има преизпълнение на операцията с 2!', ), 4 => array ( 'idOperPersCard' => 1342, 'RefNum' => '00005', 'QuantityOK' => 3, 'QuantityWaste' => 0, 'QuantityWasteSubj' => 0, 'CompleteTime' => '11.01.2018 16:05:10', 'toDo' => 2, 'Note' => 'OK', ), 5 => array ( 'idOperPersCard' => 1342, 'RefNum' => '00005', 'QuantityOK' => 1, 'QuantityWaste' => 0, 'QuantityWasteSubj' => 0, 'CompleteTime' => '11.01.2018 16:05:15', 'toDo' => 2, 'Note' => 'OK', ), 6 => array ( 'idOperPersCard' => 1342, 'RefNum' => '00005', 'QuantityOK' => 2, 'QuantityWaste' => 0, 'QuantityWasteSubj' => 0, 'CompleteTime' => '11.01.2018 16:05:35', 'toDo' => 0, 'Note' => 'OK', ), )
Ако върнатия отговор е без съобщения за грешки или несъответствия, то информацията вече успешно е предадена в съответните ПК на модул производство в Colibri® ERP и е отразен направения напредък по производствените маршрути.
Ако е необходимо, т.е. върнати са съобщения за несъответствия, могат да бъдат предприети съответните действия за коригиране на грешно подадената информация и запитването да се изпрати отново.
Използването на web service може значително да автоматизира процеса по въвеждане на изпълнението по производствените маршрути като използвайки своите права за работа с Colibri® ERP, този web service периодично изпраща събраната информация към производствените карти в модул Производство.
Разбира се трябва да се разполага с външна система за регистриране на изпълненията, която притежава своята функционалност за електронно събиране на данни за изработеното от работниците.
За съвместната работа на Colibri® ERP и външната система за електронно събиране на заработките трябва да се синхронизират списъците на персонала (по полето RefNum с помощния web service PutWorkmen) и на тройките ПК-операции-работни центрове (GetActiveOpers) за активните в момента операции по стартираните и незавършени производствени маршрути.
Ако всички данни са в синхрон, работата на разглеждания web service ще бъде безпроблемна.