От гледна точка на релационна база данни това са табиците използвани в системата.
https://restdev.erp.bg/DatabaseInfo.html
В домейн модела и съответно в REST API това са ентитита.
https://restdev.erp.bg/api_docs/
Ентититата могат да се наследяват, като в релационната база наследяването се указва чрез foreign key към базовата таблица. Този foreign key е настроен при изтриване на реда от родителската таблица да се изтрива автоматично реда от под-таблицата (cascade delete). За един ред от родителската таблица съществува точно един ред в под-таблицата т.е. връзката е едно към едно.
Например всички документни таблици имат поле Document_Id, което сочи към таблица Gen_Documents (базовата таблица на всички документи). Пример за документна таблица е Crm_Sales_Orders (Продажби), която има поле Document_Id.
Друг пример за наследяване са субектите (Gen_Parties) - всеки субект (Лице, Фирма, Филиал и др.) има поле Party_Id, което сочи към таблица Gen_Parties. При наследяване релацията винаги е едно към едно. Например когато дефинираме лице имаме един запис в таблица Cm_Persons (Лица) и един запис в Gen_Parties (Субекти). При изтриване на лицето се изтриват и двата записа.
В обектния модел наследяването става по обичайния начин. Например имаме базов абстрактен клас Document, който отговаря на таблица Gen_Documents и класове наследници (например SalesOrder отговарящ на Crm_Sales_Orders).
Бележка: Когато имаме наследяване обектът-наследник има две уникални Id-та. Едното е Id на таблицата наследник, а другото е Id на базовата таблица. Например в REST API продажбата (Crm_Sales_SalesOrders) има поле Id (както всички ентитита) и поле DocumentId.
Всяко ентити е в определен namespace в зависимост от модула в който се използва. В базата данни неймспейса е отбелязан като кратък префикс в името на таблицата. Например Crm_Sales_Orders префиксът Crm указва модула на таблицата/ентитито.
REST API е базирано на обектния модел в който неймспейсовете са дефинирани по-подробно (с под-неймспейси). Затова продажбата в REST API e Crm_Sales_SalesOrders. В неймспейс General (префикс Gen в базата данни) са дефинирани ентитита общи за всички модули.
Документацията на обектния модел се намира тук: https://restdev.erp.bg/model/
Собствени фирми са фирмите, които са собственост на предприятието използващо EnterpriseOne ERP. Всеки документ е дефиниран в конкретна собствена фирма посредством поле "Собствена фирма". Освен това всяка фирма може да има много на брой филиали (физически локации). В документа има поле "Филиал" което указва за кой филиал на собствената фирма е този документ.
В базата таблицата за собствени фирми е Gen_Enterprise_Companies, а в REST API ентитито е General_EnterpriseCompanies.
Ентити собствени фирми (General_EnterpriseCompanies) е надстройка над ентити фирми (General_Contacts_Companies) - не е наследник, а е отделно ентити, което има foreign key поле фирма. В таблицата Gen_Enterprise_Companies стоят данни специфични за собствената фирма като базова валута, език по подразбиране и други настройки използвани като стойности по подразбиране при създаване на документи и номенклатури за тази собствена фирма.
Това са ентититата които са наследници на документ. Например Продажба, Фактура, Складово нареждане, Производствено нареждане и др. В базата данни това са таблиците които съдържат специфичните данни за съответния документ. Например в таблица Crm_Sales_Orders имаме полета като Customer_Id (клиент) които имат смисъл в контекста на продажбата. В базовата таблица Gen_Documents има полета общи за всички документи от всички модули като номер на документ, дата на документ, статус и др.
За всеки вид документ може да се дефинират няколко типа документи от потребителите. Например за вид документ Продажби може да има дефинирани типове документи: Продажба от магазин, Продажба с производство, Продажба наем на актив и др.
Типовете документи са таблица Gen_Document_Types и entitiy General_DocumentTypes.
Всеки тип документ дефинира свой собствен документен поток.
При смяна на статуса на даден документ може да се настрои създаването на друг документ (от друг тип или вид). Например при пускане на продажба може да се създаде складово нареждане за изписване на стока, платежно нареждане и др. Това става чрез използването на процедури за генерация на документи, които се настройват за конкретния тип документ. Настройките на генерацията от един към друг документ стоят в ентити Systems_Workflow_Routes.
Документния поток представлява йерархичната структура на документите, като когато един документ създава друг чрез процедура за генерация то първия документ става родител на втория.
Полетата които се използват за определяне на йерархията са
- в базата данни поле Parent_Document_Id в таблица Gen_Documents.
- в REST API поле ParentDocumentId във всички документни ентитита (наследници на документ).
Съществува и поле MasterDocumentId - това е документа, който е начало на документния поток - root на дървото. Всички под-документи имат еднаква стойност в поле MasterDocumentId.
Повечето видове документи имат под-таблица с редове към тях. Например редове на продажба (таблица Crm_Sales_Order_Lines). Често наричаме документната таблица header или шапка, т.е. документа се състои от шапка и линии.
Често пъти документът се състои от няколко свързани помежду си таблици - освен Gen_Documents, шапката и линиите има и други под-таблици свързани или директно към Gen_Documents или към шапката.
В REST API за всички документи техните редове са дефинирани като navigational property. Например за Crm_Sales_SalesOrders проперти Lines връща колекция от редовете на продажбата.
Всички документи първоначално се създават на статус Нов и в последствие преминават през няколко различни системни статуса.
Различните статуси на документа са:
Полето статус в документа не може да се редактира директно. Смяна на статуса се прави със специална процедура за смяна на статута - в рест апи това е action DocumentChangeState
Обикновено смяната на статуса предизвиква процедура за генерация на друг документ - такава каквато е настроена в типа на документа.
Това са ентитита като продукти, фирми, филиали, лица, клиенти и др. които се използват за съставянето на документа.
Субектите са фирми (Company), фиалиали (CompanyLocation), лица (Person), складове (Store) и направления на фирма (CompanyDivision). Всички тези ентитита са наследници на базовото ентити Party, което е абстрактен клас.
Съществуват множество други ентитита които надграждат субекта, което означава че имат поле Party от тип Party. Например ентити клиенти (Customer) съдържа данни свързани с условията при които даден субект е клиент на дадена собствена фирма. Customer не е наследник на Party, а има поле Party. Ако искаме да създадем нов клиент то първо трябва да създадем съответния субект и после да създадем записа на клиента като подадем съответното PartyId от първата стъпка. Например ако клиента е лице създаваме запис в General_Contacts_Persons, взимаме неговото PartyId и създаваме запис в Crm_Customers.
https://enterpriseone.atlassian.net/wiki/spaces/techdoc/pages/2523318/Parties
Продуктите са стоките които се продават или произвеждат. Може да бъде и услуга която се предлага. В повечето документи продукта участва в редовете.
https://restdev.erp.bg/api_docs/#General_Products_Products
Това са пропертита дефинирани от потребителя за дадено ентити. Това става в таблица Gen_Properties където се указва код на х-ка, име на х-ка и име на ентити/таблица за която важи характеристиката.
https://restdev.erp.bg/api_docs/#customproperties
Отношението между име на ентити/таблица => име на ентити/ресурс в рест апи може да намерите тук - https://restdev.erp.bg/api_docs/entitynames.html
Това е библиотека с класове които описват ентититата като обектен модел. На нея е базирано REST API.
Базирано на odata v3 - http://www.odata.org/documentation/odata-version-3-0/
Версии - текущата версия на REST API е на адрес https://restdev.erp.bg/v17/rest/
$filter - задава филтър за поискания ресурс.
Не всички операции и функции от стандарта се поддържат.$expand - указва кои релационни пропертита на ресурса да се заредят в резултата. Иначе в резултата има само линк към тях.
$select - изброява имена на пропертита на ресурса, които ще участват в резултата. Така може да се ограничи обема на върнатите данни.
$top - броя върнати редове
$skip - броя пропуснати редове от колекцията върната след филтриране. Заедно с $top i $inlinecount се изпозлва за странициране.
$inlinecount=allpages - включва в резултата броя записи незвисимо от $top. Полето в JSON резулата е “__count”
$orderby - указва по кои полета да се сортира
cached - това не е опция от стандарта, а е специфична за EnterpriseOne REST имплементацията. Валидни стойности са true и false.
Референция с всички ентитита
https://restdev.erp.bg/api_docs/
За всяко ентити в REST API
Всяко ентити има дефинириани пропертита и навигационни пропертита.
Навигационните пропертита (или референции) са еквивалентни на foreign key в базата данни - зад всяко навигационно проперти стои съответното Id. Например в продажбата имаме проперти CustomerId и навигационно проперти Customer.
Всички заявки в рест апи се изпълняват към даден адрес на ентити (с изключение на глобалните action-и: Login,Logoff,DocumentChangeState,DocumentMakeVoid).
В резултата от заявка за дадено ентити могат да бъдат включени и полета от навигационните пропертита чрез $expand. Например в заявка за продажби можем да включим номера на клиента (за $expand ще стане дума по-късно).
В описанието на полето има указания дали то е само за четене [ReadOnly], какво филтриране поддържа [Filter], дали е задължително [Required] и дали е референция от тип "собственик" [Owner] (ако дадена референция е [Owner] можем да филтрираме текущото ентити по полета от ентитито собственик).
Как да започнем?
- Задачата трябва да е дефинирана от консултант с конкретни имена на таблици, полета и алгоритми за съответната функционалност.
- Най-често ще се налага от името на таблицата в базата данни да се открие съответното ентити в рест апи - https://restdev.erp.bg/api_docs/entitynames.html. Ако името в заданието е казано на български може да се провери в https://restdev.erp.bg/DatabaseInfo.html
Да речем че искаме да направим прост уеб магазин, който създава поръчки - https://restdev.erp.bg/api_docs/#Crm_Sales_SalesOrders
Започваме с Login заявка за отваряне на сесия.
POST https://restdev.erp.bg/v17/rest/Login
Accept:application/json;odata=light,application/json;odata=verbose
Content-Type:application/json
content:
{ServerUrl:'address-to-enterpriseone-server',Database:'database',UserName:'user',Password:'pass',Language:'bg'}
Login заявката връща ид на сесия, което трябва да се сложи в HTTP хедъра на всяка следваща заявка. Например E1-SessionId: f43ec279-1cba-4183-8f84-43094dc1f6fa. Вместо в хедъра на заявката ИД на сесията може да присъства като url параметър - sid=f43ec279-1cba-4183-8f84-43094dc1f6fa
След приключване на работа трябва да извикаме заявка Logoff.
POST https://restdev.erp.bg/v17/rest/Logoff
Accept:application/json;odata=light,application/json;odata=verbose
E1-SessionId:f43ec279-1cba-4183-8f84-43094dc1f6fa
Content-Type:application/json
Тази заявка затваря сесията изрично. Ако сесията не се използва повече от 20 минути то тя се затваря автоматично. Ако сесията е изтекла или не подадем ИД на сесия в хедъра на заявката сървъра ще върне грешка 403 Forbidden: You are not logged into EnterpriseOne. Please log in through ~/Login service action.
Друг вариант за използване на REST API е чрез Basic Authentication на адрес https://restdev.erp.bg/v17/basic/ като в User Name се пише адрес до сървъра, базата данни, езика и потребителското име, а в Password паролата на потребителя в конкретната база.
Например
username: tcp://BG1-EXT-APP14V:30031/E1_DEV_PARTNERS_TEST/bg/webuser
password: ****
Тези данни трябва да присъстват в http хедъра на всяка заявка кодирани като Base64 стринг. Например: Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l
При Basic Authentication за дадено потребителско име не може да се отвори повече от една сесия.
Чрез заявка https://restdev.erp.bg/v17/basic/?logout=true се изчиства authentication cache на браузера - т.е. това е механизъм за logout.
GET https://restdev.erp.bg/v17/rest/General_DocumentTypes?$filter=EntityName eq 'Crm_Sales_Orders'&$select=TypeName
GET https://restdev.erp.bg/v17/rest/General_EnterpriseCompanies?$expand=Company&$select=CompanyId,Company/Name
GET https://restdev.erp.bg/v17/rest/Crm_Customers?$top=10&$expand=Party&$filter=substringof('а',Party/PartyName)&$select=Party/PartyName
GET https://restdev.erp.bg/v17/rest/General_Products_Products?$top=10&$skip=20&$inlinecount=allpages&$filter=ProductGroupId eq guid'ef8197bb-e33b-46db-a180-03827d0e44f1' and substringof('lenovo',Name)
GET https://restdev.erp.bg/v17/rest/General_Products_Products?$top=10&$skip=20&$inlinecount=allpages&$filter=ProductGroupId eq guid'ef8197bb-e33b-46db-a180-03827d0e44f1' and Comp_Screen_Size eq '15'
POST https://restdev.erp.bg/rest/Crm_Sales_SalesOrders
{
"DocumentTypeId": "469b67b1-8b4b-4fb4-9d97-20c96105a85a",
"EnterpriseCompanyId": "b0e80577-fbbe-4c9b-811e-20b6c6dd465f",
"CustomerId": "2fd9dc2f-dfbf-df11-ad74-00155d00050a",
"Lines": [
{"ProductId": "12d4eb57-ed43-49e4-b8b4-78e0b45236c8", Quantity: "1"},
{"ProductId": "011579fe-baa2-4349-8912-8252594f7459", Quantity: "2"}
]
}
GET https://restdev.erp.bg/v17/rest/Crm_Sales_SalesOrders(guid'91a9bf0b-4e6b-45ae-91de-eed14f315ca5')?$expand=Customer,Customer/Party,Lines,Lines/Product&$select=DocumentId,DocumentText,Customer/Party/PartyName,Lines/LineNo,Lines/Product/Name,Lines/Quantity
POST https://restdev.erp.bg/rest/DocumentChangeState
{
"DocumentId": "f5ee220f-5137-4739-8148-23dcbb37245d",
"State": "FirmPlanned"
}