Include (KZLibrary, KZISSetup) ///

Projekt: KZIS ///

Author : M. Brousek ///

Created: 20.7.2010 ///

Description: Třída BO pro import číselníků ze systému SAP prostřednictvím csv souborů. Class KZIS.BO.SAP.ImportCodebookFiles Extends Ens.BusinessOperation [ ProcedureBlock ] { Parameter ADAPTER = "EnsLib.File.OutboundAdapter"; Parameter INVOCATION = "Queue"; /// Oddělovač položek v importovaných souborech Parameter CSVSeparator = ";"; /// Kótovací znak ohraničující hodnoty položek Parameter CSVQuoteChar; /// Počet položek importovaného záznamu číselníku nákladových středisek. ///

Používá se pro kontrolu správnosti přenášených dat a pro případ, /// kdy by hodnoty obsahovaly znak separátoru, což by vedlo k chybné interpretaci jednotlivých položek. Parameter CostCentersFieldsCount = 8; /// Počet položek importovaného záznamu číselníku dodavatelů. ///

Používá se pro kontrolu správnosti přenášených dat a pro případ, /// kdy by hodnoty obsahovaly znak separátoru, což by vedlo k chybné interpretaci jednotlivých položek. Parameter VendorsFieldsCount = 9; /// Minimální počet položek importovaného záznamu číselníku odběratelů. ///

Používá se pro kontrolu správnosti přenášených dat a pro případ, /// kdy by hodnoty obsahovaly znak separátoru, což by vedlo k chybné interpretaci jednotlivých položek. /// V případě číselníku odběratelů je místo skalární hodnoty definován povolený rozsah počtu položek, /// neboť řádka souboru nemusí obsahovat poslední položky. Parameter CustomersMinFieldsCount = 9; /// Maximální počet položek importovaného záznamu číselníku . ///

Používá se pro kontrolu správnosti přenášených dat a pro případ, /// kdy by hodnoty obsahovaly znak separátoru, což by vedlo k chybné interpretaci jednotlivých položek. /// V případě číselníku odběratelů je místo skalární hodnoty definován povolený rozsah počtu položek, /// neboť řádka souboru nemusí obsahovat poslední položky. Parameter CustomersMaxFieldsCount = 13; /// Počet položek importovaného záznamu číselníku účetních zakázek. ///

Používá se pro kontrolu správnosti přenášených dat a pro případ, /// kdy by hodnoty obsahovaly znak separátoru, což by vedlo k chybné interpretaci jednotlivých položek. Parameter BookingOrdersFieldsCount = 8; /// Počet položek importovaného záznamu vazební tabulky mezi číselníkem skupin materiálů a číselníkem tříd ocenění. ///

Používá se pro kontrolu správnosti přenášených dat a pro případ, /// kdy by hodnoty obsahovaly znak separátoru, což by vedlo k chybné interpretaci jednotlivých položek. Parameter MGroupXBClassFieldsCount = 3; /// Kódová stránka číselníku nákladových středisek Parameter CostCentersCP = "iso-8859-2"; /// Kódová stránka číselníku dodavatelů Parameter VendorsCP = "windows-1250"; /// Kódová stránka číselníku odběratelů Parameter CustomersCP = "windows-1250"; /// Kódová stránka číselníku účetních zakázek Parameter BookingOrdersCP = "iso-8859-2"; /// Kódová stránka vazební tabulky Parameter MGroupXBClassCP = "windows-1250"; /// Transakce, v rámci které byla instance třídy této BO vytvořena Property Transaction As KZIS.Data.TS.MWTransaction; /// Jméno aktuálně zpracovávaného souboru Property CurrentFileName As %String; /// Aktuální počet nastalých chyb Property ErrorCount As %Integer; /// Instace souboru pro logování chybných záznamů Property LogFile As KZIS.MW.LogFile; /// Inicializace importu každé entity přenášené tímto BP. ///

Obsahuje počáteční nastavení, které je společné pro všechny relevantní entity. Method InitImport() { set ..ErrorCount = 0 set ..LogFile = ##class(KZIS.MW.LogFile).%New() set ..LogFile.Directory = $$$ArchivFullPath($$$SAPArchivDir, ..Transaction.TransactionID) set ..Adapter.FilePath = $$$KZISDataFullPath_$$$SAPIncomingDir } /// Dokončení importu každé entity přenášené tímto BP. ///

Obsahuje operace, které jsou společné pro všechny relevantní entity. /// V tomto případě přesun zpracovaného souboru do archivu. V případě nastalé chyby /// pak uzavře logovací soubor a vyvolá výjimku, která ukončí příslušný proces. Method DoneImport() { do ..MoveFileToArchiv() if (..ErrorCount '= 0) { do ..LogFile.Close() set ..LogFile = "" // throw $$$KZISError("Error importing file: "_..CurrentFileName, "Error count: "_..ErrorCount) } } /// Zaznamená nastalou chybu a její popis Method LogDataError(pMessage As %String) { set ..ErrorCount = ..ErrorCount + 1 $$$LOGERROR(pMessage) } /// Přesune aktuálně zpracovávaný soubor do archivu Method MoveFileToArchiv() { set tSourceFileName = ..Adapter.fixPath(..Adapter.FilePath)_..CurrentFileName set tArchivFileName = $$$ArchivFullPath($$$SAPArchivDir, ..Transaction.TransactionID)_..CurrentFileName if ##class(%File).Exists(tArchivFileName) do ##class(%File).Delete(tArchivFileName) set tSC = ##class(%File).Rename(tSourceFileName, tArchivFileName) if 'tSC $$$LOGERROR("Could not move '"_tSourceFileName_"' to KZIS archiv directory '"_tArchivFileName_"'") } /// Transformace řádky souboru nákladových středisek do atributů příslušné třídy. Method AddCostCenterRec(pLine As %String, ByRef pRec As KZIS.Data.DS.CostCenter) { set Values = $LISTFROMSTRING(pLine, ..#CSVSeparator) //Kontrola na správný počet položek záznamu. //Nalezne také případnou chybu způsobenou tím, že některá hodnota obsahovala znak separátoru if $LISTLENGTH(Values) '= ..#CostCentersFieldsCount { do ..LogDataError("List length: "_$LISTLENGTH(Values)_"; expected length: "_..#CostCentersFieldsCount) do ..LogFile.Update(pLine) q } //Jednotlivé položky seznamu mají dané pořadí¨ set pRec.ObjID = $LIST(Values, 1) //set pRec.Parent = .... set pRec.Number = $LIST(Values, 1) set pRec.ParentNo = $LIST(Values, 2) set pRec.ShortName = $LIST(Values, 3) set pRec.LongName = $LIST(Values, 4) set pRec.Kind = $LIST(Values, 7) set pRec.InvDept = $LIST(Values, 8) //set pRec.Official = $LIST(Values, ) set pRec.ValidFrom = $$$SAPToDateFrom($LIST(Values, 5)) set pRec.ValidTo = $$$SAPToDateTo($LIST(Values, 6)) } /// Transformace řádky souboru dodavatelů do atributů příslušné třídy. Method AddVendorRec(pLine As %String, ByRef pRec As KZIS.Data.DS.Vendor) { set Values = $LISTFROMSTRING(pLine, ..#CSVSeparator) //Kontrola na správný počet položek záznamu. //Nalezne také případnou chybu způsobenou tím, že některá hodnota obsahovala znak separátoru if $LISTLENGTH(Values) '= ..#VendorsFieldsCount { do ..LogDataError("List length: "_$LISTLENGTH(Values)_"; expected length: "_..#VendorsFieldsCount) do ..LogFile.Update(pLine) q } //Jednotlivé položky seznamu mají dané pořadí¨ set pRec.ObjID = $LIST(Values, 1) set pRec.Number = $LIST(Values, 1) set pRec.Name = $LIST(Values, 2) set pRec.State = $LIST(Values, 9) set pRec.City = $LIST(Values, 5) set pRec.Street = $LIST(Values, 4) //set pRec.HouseNo = $LIST(Values, ) set pRec.ZipCode = $LIST(Values, 6) set pRec.ICO = $LIST(Values, 8) set pRec.DIC = $LIST(Values, 7) set pRec.Active = 1 } /// Transformace řádky souboru odběratelů do atributů příslušné třídy. Method AddCustomerRec(pLine As %String, ByRef pRec As KZIS.Data.DS.Customer) { set Values = $LISTFROMSTRING(pLine, ..#CSVSeparator) //Kontrola na správný počet položek záznamu. //Nalezne také případnou chybu způsobenou tím, že některá hodnota obsahovala znak separátoru //Úprava ze dne 12.10.2010 kontroluje pouze rozsah počtu položek. Přenášená věta totiž může //obsahovat menší počet položek, kdy nevyplněné položky na konci záznamu nejsou uvedeny. if (($LISTLENGTH(Values) > ..#CustomersMaxFieldsCount) || ($LISTLENGTH(Values) < ..#CustomersMinFieldsCount)) { do ..LogDataError("List length: "_$LISTLENGTH(Values)_"; expected length: "_..#CustomersMinFieldsCount_" - "_..#CustomersMaxFieldsCount) do ..LogFile.Update(pLine) q } //Jednotlivé položky seznamu mají dané pořadí¨ set pRec.ObjID = $LIST(Values, 1) set pRec.Number = $LIST(Values, 1) set pRec.Name = $LIST(Values, 2) set pRec.State = $LIST(Values, 4) set pRec.City = $LIST(Values, 5) set pRec.ZipCode = $LIST(Values, 6) set pRec.Street = $LIST(Values, 7) //set pRec.HouseNo = $LIST(Values, ) if ($LISTLENGTH(Values) > 9) set pRec.DIC = $LIST(Values, 10) if ($LISTLENGTH(Values) > 10) set pRec.ICO = $LIST(Values, 11) if ($LISTLENGTH(Values) > 11) set pRec.BankAccount = $LIST(Values, 12) if ($LISTLENGTH(Values) > 12) set pRec.BankCode = $LIST(Values, 13) set pRec.Active = 1 } /// Transformace řádky souboru účetních zakázek do atributů příslušné třídy. Method AddBookingOrderRec(pLine As %String, ByRef pRec As KZIS.Data.DS.BookingOrder) { set Values = $LISTFROMSTRING(pLine, ..#CSVSeparator) //Kontrola na správný počet položek záznamu. //Nalezne také případnou chybu způsobenou tím, že některá hodnota obsahovala znak separátoru if $LISTLENGTH(Values) '= ..#BookingOrdersFieldsCount { do ..LogDataError("List length: "_$LISTLENGTH(Values)_"; expected length: "_..#BookingOrdersFieldsCount) do ..LogFile.Update(pLine) q } //Jednotlivé položky seznamu mají dané pořadí¨ set pRec.ObjID = $LIST(Values, 1) set pRec.Number = $LIST(Values, 1) set pRec.Branch = $LIST(Values, 2) set pRec.ShortName = $LIST(Values, 3) set pRec.LongName = $LIST(Values, 4) set pRec.ValidFrom = $$$SAPToDateFrom($LIST(Values, 5)) set pRec.ValidTo = $$$SAPToDateTo($LIST(Values, 6)) set pRec.Kind = $LIST(Values, 7) } /// Transformace řádky souboru vazební tabulky do atributů příslušné třídy. Method AddMGroupXBClassRec(pLine As %String, ByRef pRec As KZIS.Data.DS.MatGroupXBookingClass) { set Values = $LISTFROMSTRING(pLine, ..#CSVSeparator) //Kontrola na správný počet položek záznamu. //Nalezne také případnou chybu způsobenou tím, že některá hodnota obsahovala znak separátoru if $LISTLENGTH(Values) '= ..#MGroupXBClassFieldsCount { do ..LogDataError("List length: "_$LISTLENGTH(Values)_"; expected length: "_..#MGroupXBClassFieldsCount) do ..LogFile.Update(pLine) q } //Jednotlivé položky seznamu mají dané pořadí¨ /* set pRec.MGroupNumber = $LIST(Values, 1) set pRec.MGroupName = $LIST(Values, 2) set pRec.BClassNumber = $LIST(Values, 3) */ set pRec.BClassNumber = $LIST(Values, 1) set pRec.MGroupNumber = $LIST(Values, 2) set pRec.MGroupName = $LIST(Values, 3) } /// Výkonná metoda pro import číselníku nákladových středisek do DB MW. Method CostCentersIN() { set ..CurrentFileName = $$$SAPCostCentersFileName set ..LogFile.FileName = ..CurrentFileName $$$LOGINFO("SAP Importing file: "_..Adapter.fixPath(..Adapter.FilePath)_..CurrentFileName) set ..Adapter.Charset = ..#CostCentersCP set tSC = ..Adapter.GetStream(..CurrentFileName, .tStream) if $$$ISERR(tSC) { throw $$$KZISError("BO SAP.ImportCSVFiles CostCentersIN error:", "Error reading source file") } while 'tStream.AtEnd { set tLine = tStream.ReadLine() //Create new record instance set tNewRec = ##class(KZIS.Data.DS.CostCenter).%New() set tNewRec.Transaction = ..Transaction try { do ..AddCostCenterRec(tLine, .tNewRec) if (tNewRec.Number '= "") && '##class(KZIS.Data.DS.CostCenter).Exists(tNewRec.Number, ..Transaction.%Id()) { set tSC = tNewRec.%Save() if $$$ISERR(tSC) { throw $$$KZISError("BO SAP.ImportCSVFiles AddCostCenterRec", "Error saving new rec: "_##class(%SYSTEM.Status).GetErrorText(tSC)) } } } catch E { do ..LogDataError("BO SAP.ImportCSVFiles AddCostCenterRec exception: "_E.Location_"; "_E.Name_" - "_E.Data) do ..LogFile.Update(tLine) } } } /// Výkonná metoda pro import číselníku dodavatelů do DB MW. Method VendorsIN() { set ..CurrentFileName = $$$SAPVendorsFileName set ..LogFile.FileName = ..CurrentFileName $$$LOGINFO("SAP Importing file: "_..Adapter.fixPath(..Adapter.FilePath)_..CurrentFileName) set ..Adapter.Charset = ..#VendorsCP set tSC = ..Adapter.GetStream(..CurrentFileName, .tStream) if $$$ISERR(tSC) { throw $$$KZISError("BO SAP.ImportCSVFiles VendorsIN error:", "Error reading source file") } while 'tStream.AtEnd { set tLine = tStream.ReadLine() //Create new record instance set tNewRec = ##class(KZIS.Data.DS.Vendor).%New() set tNewRec.Transaction = ..Transaction try { do ..AddVendorRec(tLine, .tNewRec) if (tNewRec.Number '= "") && '##class(KZIS.Data.DS.Vendor).Exists(tNewRec.Number, ..Transaction.%Id()) { set tSC = tNewRec.%Save() if $$$ISERR(tSC) { throw $$$KZISError("BO SAP.ImportCSVFiles AddVendorRec", "Error saving new rec: "_##class(%SYSTEM.Status).GetErrorText(tSC)) } } } catch E { do ..LogDataError("BO SAP.ImportCSVFiles AddVendorRec exception: "_E.Location_"; "_E.Name_" - "_E.Data) do ..LogFile.Update(tLine) } } } /// Výkonná metoda pro import číselníku odběratelů do DB MW. Method CustomersIN() { set ..CurrentFileName = $$$SAPCustomersFileName set ..LogFile.FileName = ..CurrentFileName $$$LOGINFO("SAP Importing file: "_..Adapter.fixPath(..Adapter.FilePath)_..CurrentFileName) set ..Adapter.Charset = ..#CustomersCP set tSC = ..Adapter.GetStream(..CurrentFileName, .tStream) if $$$ISERR(tSC) { throw $$$KZISError("BO SAP.ImportCSVFiles CustomersIN error:", "Error reading source file") } while 'tStream.AtEnd { set tLine = tStream.ReadLine() //Create new record instance set tNewRec = ##class(KZIS.Data.DS.Customer).%New() set tNewRec.Transaction = ..Transaction try { do ..AddCustomerRec(tLine, .tNewRec) if (tNewRec.Number '= "") && '##class(KZIS.Data.DS.Customer).Exists(tNewRec.Number, ..Transaction.%Id()) { set tSC = tNewRec.%Save() if $$$ISERR(tSC) { throw $$$KZISError("BO SAP.ImportCSVFiles AddCustomerRec", "Error saving new rec: "_##class(%SYSTEM.Status).GetErrorText(tSC)) } } } catch E { do ..LogDataError("BO SAP.ImportCSVFiles AddCustomerRec exception: "_E.Location_"; "_E.Name_" - "_E.Data) do ..LogFile.Update(tLine) } } } /// Výkonná metoda pro import číselníku účetních zakázek do DB MW. Method BookingOrdersIN() { set ..CurrentFileName = $$$SAPBookingOrdersFileName set ..LogFile.FileName = ..CurrentFileName $$$LOGINFO("SAP Importing file: "_..Adapter.fixPath(..Adapter.FilePath)_..CurrentFileName) set ..Adapter.Charset = ..#BookingOrdersCP set tSC = ..Adapter.GetStream(..CurrentFileName, .tStream) if $$$ISERR(tSC) { throw $$$KZISError("BO SAP.ImportCSVFiles BookingOrdersIN error:", "Error reading source file") } while 'tStream.AtEnd { set tLine = tStream.ReadLine() //Create new record instance set tNewRec = ##class(KZIS.Data.DS.BookingOrder).%New() set tNewRec.Transaction = ..Transaction try { do ..AddBookingOrderRec(tLine, .tNewRec) if (tNewRec.Number '= "") && '##class(KZIS.Data.DS.BookingOrder).Exists(tNewRec.Number, ..Transaction.%Id()) { set tSC = tNewRec.%Save() if $$$ISERR(tSC) { throw $$$KZISError("BO SAP.ImportCSVFiles AddBookingOrderRec", "Error saving new rec: "_##class(%SYSTEM.Status).GetErrorText(tSC)) } } } catch E { do ..LogDataError("BO SAP.ImportCSVFiles AddBookingOrderRec exception: "_E.Location_"; "_E.Name_" - "_E.Data) do ..LogFile.Update(tLine) } } } /// Výkonná metoda pro import vazební tabulky skupin materiálů x třída ocenění do DB MW. Method MGroupXBClassIN() { set ..CurrentFileName = $$$SAPMGroupXBClassFileName set ..LogFile.FileName = ..CurrentFileName $$$LOGINFO("SAP Importing file: "_..Adapter.fixPath(..Adapter.FilePath)_..CurrentFileName) set ..Adapter.Charset = ..#MGroupXBClassCP set tSC = ..Adapter.GetStream(..CurrentFileName, .tStream) if $$$ISERR(tSC) { throw $$$KZISError("BO SAP.ImportCSVFiles MGroupXBClassIN error:", "Error reading source file") } while 'tStream.AtEnd { set tLine = tStream.ReadLine() //Create new record instance set tNewRec = ##class(KZIS.Data.DS.MatGroupXBookingClass).%New() set tNewRec.Transaction = ..Transaction try { do ..AddMGroupXBClassRec(tLine, .tNewRec) if (tNewRec.MGroupNumber '= "") && '##class(KZIS.Data.DS.MatGroupXBookingClass).Exists(tNewRec.MGroupNumber, ..Transaction.%Id()) { set tSC = tNewRec.%Save() if $$$ISERR(tSC) { throw $$$KZISError("BO SAP.ImportCSVFiles AddMGroupXBClassRec", "Error saving new rec: "_##class(%SYSTEM.Status).GetErrorText(tSC)) } } } catch E { do ..LogDataError("BO SAP.ImportCSVFiles AddMGroupXBClassRec exception: "_E.Location_"; "_E.Name_" - "_E.Data) do ..LogFile.Update(tLine) } } } /// Metoda, zpracovávající došlý požadavek na uložení dat číselníků z csv souborů, /// které byly exportovány ze SAPu. ///

Provádí spuštění příslušné výkonné metody podle kódu druhu transakce, /// obsaženého ve vstupním požadavku pRequest. /// V případě, že požadavek obsahuje kód transakce, která není v rámci přenosu definována, /// vyvolá metoda výjimku, která ukončí daný proces. /// Viz též třída požadavku KZIS.Msg.MW.BODataRequest. /// Zatím je v rámci konektoru Apothéké definován pouze import souboru materiálů lékárny. Method ImportCSVFile(pRequest As KZIS.Msg.MW.BODataRequest, Output pResponse As KZIS.Msg.MW.CommonDataResponse) As %Status { $$$LOGINFO("SAP Import CSV file: 'Starting operation'") Quit:'$ISOBJECT(pRequest) $$$ERROR($$$GeneralError,"SAP.ImportCSVFile: 'Request missing'") Quit:'$ISOBJECT(pRequest.Transaction) $$$ERROR($$$GeneralError,"SAP.ImportCSVFile: 'Transaction missing'") TRY { set ..Transaction = pRequest.Transaction do ..InitImport() set pResponse = ##class(KZIS.Msg.MW.CommonDataResponse).%New() set pResponse.Transaction = pRequest.Transaction if pRequest.KindCode = $$$tkcSAPCostCenters { do ..CostCentersIN() } elseif pRequest.KindCode = $$$tkcSAPVendors { do ..VendorsIN() } elseif pRequest.KindCode = $$$tkcSAPCustomers { do ..CustomersIN() } elseif pRequest.KindCode = $$$tkcSAPBookingOrders { do ..BookingOrdersIN() } elseif pRequest.KindCode = $$$tkcSAPMGroupXBClass { do ..MGroupXBClassIN() } else { throw $$$KZISError("BO SAP.ImportCSVFile error:", "Invalid transaction kind code") } do ..DoneImport() $$$LOGINFO("SAP.ImportCSVFile '"_pRequest.Transaction.Kind.Description_"' finished") set tSC = $$$OK } CATCH E { $$$LOGERROR("Operation 'SAP.ImportCSVFiles' error: Exception("_E.Location_": "_E.Name_" - "_E.Data_")") set tSC = $$$ERROR($$$GeneralError) } Quit tSC } /// Zkušbní metoda pro testování této BO v testovacím prostředí portálu Ensemble. Method TestExport(pRequest As Ens.Request, Output pResponse As KZIS.Msg.MW.CommonDataResponse) As %Status { set ..Transaction = pRequest.Transaction set pResponse = ##class(KZIS.Msg.MW.CommonDataResponse).%New() do ..CustomersIN() Quit $$$OK } XData MessageMap { ImportCSVFile TestExport } }