====== Opis aplikacji ====== **Aplikacja będzie miała za zadanie katalogować i zarządzać szkoleniami BHP, a ponadto móc generować raporty z bieżącego szkolenia jak i ze szkoleń w historii. Docelowym użytkownikiem aplikacji będzie pojedynczy, zewnętrzny szkoleniowiec prowadzący szkolenia w pewnych zakładach pracy i mający pod opieką pewną grupę pracowników dla których konieczne są szkolenia, zarówno jednorazowe jak i okresowe.** ===== Opis funkcjonalny ===== ==== Pracownicy ==== Katalogowanie pracowników będzie polegać na ich grupowaniu względem zakładu pracy w którym pracują oraz wyświetlaniu wszystkich informacji powiązanych z danym pracownikiem. Jednocześnie będą dostępne zbiorcze zestawienia pracowników w celu przeglądu z możliwością sortowania względem wybranych informacji. Kolejnym elementem będzie rozbudowany filtr, umożliwiający przeszukiwanie bazy względem wielu kryteriów dotyczących pracowników i informacji z nimi związanych.\\ \\ Z każdym pracownikiem będą związane następujące informacje:\\ * dane teleadresowe * informacje o zakładzie pracy w którym pracuje * informacje o aktualnie ważnym badaniu lekarskim * informacje o aktualnie ważnym szkoleniu * pełna historia odbytych szkoleń ==== Zakłady pracy ==== Pracownicy będą katalogowani względem zakładów pracy w których pracują. Dodatkowo będzie zaimplementowana złożona wyszukiwarka tychże zakładów.\\ \\ Z każdym zakładem pracy będą związane następujące informacje:\\ * dane teleadresowe * lista pracowników ==== Kategorie szkoleń ==== Kategorie szkoleń będą tworzyły reprezentację różnych rodzajów szkoleń jakie są charakterystyczne dla poszczególnych grup pracowników, np. pracownicy fizyczni lub pracujący w szczególnych warunkach zdrowotnych. Kategorie szkoleń będą również kolejną metodą grupowania pracowników, gdyż każdy z pracowników, po odbyciu szkolenia będzie klasyfikowany do pewnej grupy zawodowej. Dla kategorii będzie również zaimplementowana złożona wyszukiwarka.\\ \\ Dla kategorii szkoleń będą charakterystyczne następujące informacje: * nazwa, opis kategorii * okres ważności wskazujący po jakim czasie pracownik powinien być przeszkolony ponownie * liczba przeprowadzonych szkoleń * plik szablonu raportu, wskazujący szablon który powinien zostać użyty przy generowaniu raportu dla danego szkolenia ==== Szkolenia ==== Na wcześniej wybranej grupie pracowników, użytkownik będzie mógł przeprowadzić szkolenie zadanej kategorii. Informacja o szkoleniu zostanie dodana do historii szkoleń, a wszystkie inne informacje w bazie zostaną odpowiednio uaktualnione. Dodatkowo zostanie wygenerowany odpowiedni dla danej kategorii plik raportu, zawierające informacje na temat przeprowadzonego szkolenia a przeznaczony do wydruku. Plik wygenerowanego raportu również zostanie zapisany w historii. Dodatkowo będzie zaimplementowana rozbudowana wyszukiwarka.\\ \\ Dla poszczególnych szkoleń będą dostępne następujące informacje:\\ * charakterystyczny numer identyfikujący poszczególne szkolenia * kategoria, opis * data szkolenia * data ważności * plik szablonu raportu, który został użyty ==== Historia szkoleń ==== Wszystkie przeprowadzone szkolenia będą zapisywane. Będzie można przeglądać pełną historię przeprowadzonych szkoleń jak i historię szkoleń dla każdego pracownika z osobna. Dodatkowo będzie zaimplementowana rozbudowana wyszukiwarka. ==== Raporty ==== Raporty będą generowane po przeprowadzeniu szkolenia na podstawie wcześniej zdefiniowanych plików szablonów. Pliki szablonów będą reprezentowane przez dokumenty typu OpenXML, zawierające strukturę raportu ze zdefiniowanymi polami-argumentami, które będą uzupełniane informacjami charakterystycznymi dla przeprowadzonego szkolenia. Raporty automatycznie będą drukowane, z możliwością ponownego ich odtworzenia z historii szkoleń. ===== Technologie ===== ==== Środowisko implementacji ==== * MS Visual Studio 2010 * .NET Framework 4.0 * MS SQL Server 2008 R2 * MS Word 2007 * Open XML SDK 2.0 ==== Elementy do wdrożenia testowego ==== * Użycie bazy danych SQLExpress, przechowującej dane w pojedynczym pliku dołączanym do właściwej aplikacji. Rozwiązanie zapewnia niemal pełną funkcjonalność standardowej bazy danych bez konieczności instalowania bazy w silniku serwera. Wydaje się to być ciekawym rozwiązaniem dla aplikacji mającej stosunkowo niewielki narzut danych. * Użycie funkcji CLR (implementowanych przy użyciu C# i .NET Framework) wewnątrz bazy danych. Funkcje mogłyby zapewnić integralność informacji o plikach, przechowywanych w bazie z ich fizyczną reprezentacją na dysku na poziomie mechanizmów samej bazy. * Użycie biblioteki Open XML SDK 2.0 dającej możliwość manipulacją plikami formatu OpenXML w celu generowania elastycznych raportów na podstawie wcześniej przygotowywanych, standardowych i łatwych w tworzeniu dokumentów pakietu MS Office 2007 lub OpenOffice. \\ ====== Projekt bazy danych ====== Baza danych będzie implementowana jako darmowa baza SQLExpress, która jest oparta na komercyjnym SZBD MS SQL Server 2008 R2. ===== Tabele ===== {{:pl:dydaktyka:ztb:2010:projekty:menadzer_szkolen:database_diagram.gif|}} \\ ===== Wyzwalacze ===== Implementacja dodatkowych wyzwalaczy była konieczna ze względu na to, że MS SQL Server nie dopuszcza definiowania kluczy obcych, które tworzyły by w bazie zapętlone wywołania //ON DELETE ACTION// lub //ON UPDATE ACTION//. ==== Wyzwalacze dla tabeli Template ==== Wyzwalacz utrzymuje więzy integralności z innymi tabelami w przypadku usuwania danych. CREATE TRIGGER [dbo].[ForDeleteTemplateTrigger] ON [dbo].[Template] FOR DELETE AS -- aktualizacja tabeli Training UPDATE dbo.Training SET ProtocolTemplateId = NULL WHERE ProtocolTemplateId IN (SELECT Id FROM deleted) UPDATE dbo.Training SET CertificateTemplateId = NULL WHERE CertificateTemplateId IN (SELECT Id FROM deleted) -- aktualizacja tabeli TrainingCategory UPDATE dbo.TrainingCategory SET ProtocolTemplateId = NULL WHERE ProtocolTemplateId IN (SELECT Id FROM deleted) UPDATE dbo.TrainingCategory SET CertificateTemplateId = NULL WHERE CertificateTemplateId IN (SELECT Id FROM deleted) GO \\ Wyzwalacz utrzymuje więzy integralności z innymi tabelami w przypadku modyfikowania klucza głównego. -- Utrzymuje więzy integralności innych tabel z tabelą Template w przypadku modyfikowania klucza głównego. CREATE TRIGGER [dbo].[ForUpdateTemplateTrigger] ON [dbo].[Template] FOR UPDATE AS -- aktualizacja tabel TrainingCategory i Training IF UPDATE(Id) BEGIN DECLARE @insertedId uniqueidentifier, @deletedId uniqueidentifier DECLARE ForUpdateInsertedRowsCursor CURSOR FOR SELECT Id FROM inserted DECLARE ForUpdateDeletedRowsCursor CURSOR FOR SELECT Id FROM deleted OPEN ForUpdateInsertedRowsCursor OPEN ForUpdateDeletedRowsCursor FETCH NEXT FROM ForUpdateInsertedRowsCursor INTO @insertedId FETCH NEXT FROM ForUpdateDeletedRowsCursor INTO @deletedId WHILE @@FETCH_STATUS = 0 BEGIN -- aktualizacja tabeli TrainingCategory UPDATE dbo.TrainingCategory SET ProtocolTemplateId = @insertedId WHERE ProtocolTemplateId = @deletedId UPDATE dbo.TrainingCategory SET CertificateTemplateId = @insertedId WHERE CertificateTemplateId = @deletedId -- aktualizacja tabeli Training UPDATE dbo.Training SET ProtocolTemplateId = @insertedId WHERE ProtocolTemplateId = @deletedId UPDATE dbo.Training SET CertificateTemplateId = @insertedId WHERE CertificateTemplateId = @deletedId -- wczytanie kolejnego rekordu FETCH NEXT FROM ForUpdateInsertedRowsCursor INTO @insertedId FETCH NEXT FROM ForUpdateDeletedRowsCursor INTO @deletedId END CLOSE ForUpdateInsertedRowsCursor CLOSE ForUpdateDeletedRowsCursor DEALLOCATE ForUpdateInsertedRowsCursor DEALLOCATE ForUpdateDeletedRowsCursor END ==== Wyzwalacze dla tabeli TrainingCategory ==== Wyzwalacz utrzymuje więzy integralności z innymi tabelami w przypadku usuwania danych. CREATE TRIGGER [dbo].[DeleteTrainingCategoryTrigger] ON [dbo].[TrainingCategory] FOR DELETE AS -- aktualizacja tabeli Training UPDATE dbo.Training SET TrainingCategoryId = NULL WHERE TrainingCategoryId IN (SELECT Id FROM deleted) GO \\ Wyzwalacz utrzymuje więzy integralności z innymi tabelami w przypadku modyfikowania klucza głównego. CREATE TRIGGER [dbo].[UpdateTrainingCategoryTrigger] ON [dbo].[TrainingCategory] FOR UPDATE AS -- aktualizacja tabeli Training IF UPDATE(Id) BEGIN DECLARE @insertedId uniqueidentifier, @deletedId uniqueidentifier DECLARE InsertedRowsCursor CURSOR FOR SELECT Id FROM inserted DECLARE DeletedRowsCursor CURSOR FOR SELECT Id FROM deleted OPEN InsertedRowsCursor OPEN DeletedRowsCursor FETCH NEXT FROM InsertedRowsCursor INTO @insertedId FETCH NEXT FROM DeletedRowsCursor INTO @deletedId WHILE @@FETCH_STATUS = 0 BEGIN UPDATE dbo.Training SET TrainingCategoryId = @insertedId WHERE TrainingCategoryId = @deletedId FETCH NEXT FROM InsertedRowsCursor INTO @insertedId FETCH NEXT FROM DeletedRowsCursor INTO @deletedId END CLOSE InsertedRowsCursor CLOSE DeletedRowsCursor DEALLOCATE InsertedRowsCursor DEALLOCATE DeletedRowsCursor END ===== Widoki ===== ==== Widok zakładu pracy ==== Widok umożliwia wybranie istotnych dla użytkownika informacji dla danego zakładu pracy. === Diagram === {{:pl:dydaktyka:ztb:2010:projekty:menadzer_szkolen:companymainview.gif|}} === Skrypt === CREATE VIEW [dbo].[TrainingCategoryView] AS SELECT dbo.TrainingCategory.Id, dbo.TrainingCategory.Name, dbo.TrainingCategory.ExpiryTime, dbo.TrainingCategory.Description, dbo.TrainingCategory.LastNumber, ProtocolTemplate.Name AS ProtocolName, CertificateTemplate.Name AS CertificateName, ProtocolTemplate.Id AS ProtocolId, CertificateTemplate.Id AS CertificateId FROM dbo.Template AS CertificateTemplate RIGHT OUTER JOIN dbo.TrainingCategory ON CertificateTemplate.Id = dbo.TrainingCategory.CertificateTemplateId LEFT OUTER JOIN dbo.Template AS ProtocolTemplate ON dbo.TrainingCategory.ProtocolTemplateId = ProtocolTemplate.Id ==== Widok pracownika ==== Widok grupuje informacje na temat pracownika, jego zakładu pracy oraz aktualnie ważnego szkolenia. === Diagram === {{:pl:dydaktyka:ztb:2010:projekty:menadzer_szkolen:employeemainview.gif|}} === Skrypt === CREATE VIEW [dbo].[EmployeeDetailsView] AS SELECT dbo.Employee.Surname, dbo.Employee.Forename, dbo.Employee.Street, dbo.Employee.BuildingNumber, dbo.Employee.FlatNumber, dbo.Employee.City, dbo.Employee.PostalCode, dbo.Employee.Post, dbo.Employee.Phone, dbo.Employee.Email, dbo.Employee.BirthDate, dbo.Employee.BirthPlace, dbo.Employee.Position, dbo.Employee.CheckupExpiryDate, dbo.Employee.Id, dbo.Company.Name, dbo.Employee.CompanyId, dbo.Training.Number, dbo.Training.TrainingDate, dbo.Training.ExpiryDate, dbo.TrainingCategory.Name AS CategoryName FROM dbo.TrainingCategory RIGHT OUTER JOIN dbo.Training ON dbo.TrainingCategory.Id = dbo.Training.TrainingCategoryId RIGHT OUTER JOIN dbo.Company INNER JOIN dbo.Employee ON dbo.Company.Id = dbo.Employee.CompanyId ON dbo.Training.Id = dbo.Employee.CurrentTrainingId ==== Widok kategorii szkoleń ==== Widok grupuje informacje na temat szkoleń i przypisanych raportów. === Diagram === {{:pl:dydaktyka:ztb:2010:projekty:menadzer_szkolen:trainingcategoryview.gif|}} === Skrypt === CREATE VIEW [dbo].[TrainingCategoryView] AS SELECT dbo.TrainingCategory.Id, dbo.TrainingCategory.Name, dbo.TrainingCategory.ExpiryTime, dbo.TrainingCategory.Description, dbo.TrainingCategory.LastNumber, ProtocolTemplate.Name AS ProtocolName, CertificateTemplate.Name AS CertificateName, ProtocolTemplate.Id AS ProtocolId, CertificateTemplate.Id AS CertificateId FROM dbo.Template AS CertificateTemplate RIGHT OUTER JOIN dbo.TrainingCategory ON CertificateTemplate.Id = dbo.TrainingCategory.CertificateTemplateId LEFT OUTER JOIN dbo.Template AS ProtocolTemplate ON dbo.TrainingCategory.ProtocolTemplateId = ProtocolTemplate.Id ==== Widok historii szkoleń ==== Widok grupuje informacje na temat szkoleń, ich kategorii oraz przypisanych raportów. === Diagram === {{:pl:dydaktyka:ztb:2010:projekty:menadzer_szkolen:traininghistoryview.gif|}} === Skrypt === CREATE VIEW [dbo].[TrainingHistoryView] AS SELECT dbo.Training.Id, dbo.Training.Number, dbo.Training.TrainingDate, dbo.Training.ExpiryDate, dbo.Training.Description, dbo.TrainingCategory.Name AS CategoryName, ProtocolTemplate.Name AS ProtocolName, CertificateTemplate.Name AS CertificateName, ProtocolTemplate.Id AS ProtocolId, CertificateTemplate.Id AS CertificateId, ProtocolTemplate.FileName AS ProtocolFileName, CertificateTemplate.FileName AS CertificateFileName FROM dbo.Template AS ProtocolTemplate RIGHT OUTER JOIN dbo.Training ON ProtocolTemplate.Id = dbo.Training.ProtocolTemplateId LEFT OUTER JOIN dbo.TrainingCategory ON dbo.Training.TrainingCategoryId = dbo.TrainingCategory.Id LEFT OUTER JOIN dbo.Template AS CertificateTemplate ON dbo.Training.CertificateTemplateId = CertificateTemplate.Id \\ ===== Funkcje ===== ==== IsTemplateUsing ==== Funkcja sprawdza czy dany plik szablonu jest gdziekolwiek wykorzystywany w bazie. Funkcja umożliwi wielokrotne wykorzystywanie tego samego pliku i jednocześnie automatyczne jego usuwanie, jeżeli nie będzie już potrzebny. === Skrypt === CREATE FUNCTION [dbo].[IsTempleteUsing] ( @templateIdParam uniqueidentifier ) RETURNS BIT AS BEGIN IF EXISTS (SELECT Id FROM TrainingCategory WHERE ProtocolTemplateId = @templateIdParam) RETURN 1 IF EXISTS (SELECT Id FROM TrainingCategory WHERE CertificateTemplateId = @templateIdParam) RETURN 1 IF EXISTS (SELECT Id FROM Training WHERE ProtocolTemplateId = @templateIdParam) RETURN 1 IF EXISTS (SELECT Id FROM Training WHERE CertificateTemplateId = @templateIdParam) RETURN 1 RETURN 0 END \\ ===== Procedury ===== ==== SelectTrainingsByEmployeeId ==== Procedura umożliwia wybranie rekordów wszystkich szkoleń w których uczestniczył zadany pracownik. === Skrypt === CREATE PROCEDURE [dbo].[SelectTrainingsByEmployeeId] @employeeIdParam uniqueidentifier AS SET NOCOUNT ON; SELECT * FROM dbo.TrainingHistoryView WHERE (Id IN (SELECT TrainingId FROM dbo.EmployeeTraining WHERE (EmployeeId = @employeeIdParam))); RETURN ==== SelectEmployeesByTrainingId ==== Procedura umożliwia wybranie wszystkich rekordów pracowników, którzy uczestniczyli w zadanym szkoleniu. === Skrypt === CREATE PROCEDURE [dbo].[SelectEmployeesByTrainingId] @trainingIdParam uniqueidentifier AS SET NOCOUNT ON; SELECT EmployeeDetailsView.Surname, EmployeeDetailsView.Forename, EmployeeDetailsView.Street, EmployeeDetailsView.BuildingNumber, EmployeeDetailsView.FlatNumber, EmployeeDetailsView.City, EmployeeDetailsView.PostalCode, EmployeeDetailsView.Post, EmployeeDetailsView.Phone, EmployeeDetailsView.Email, EmployeeDetailsView.BirthDate, EmployeeDetailsView.BirthPlace, EmployeeDetailsView.Position, EmployeeDetailsView.CheckupExpiryDate, EmployeeDetailsView.Id, EmployeeDetailsView.Name, EmployeeDetailsView.CompanyId, EmployeeDetailsView.Number, EmployeeDetailsView.TrainingDate, EmployeeDetailsView.ExpiryDate, EmployeeDetailsView.CategoryName FROM EmployeeTraining INNER JOIN EmployeeDetailsView ON EmployeeTraining.EmployeeId = EmployeeDetailsView.Id WHERE (EmployeeTraining.TrainingId = @trainingIdParam) RETURN \\ ====== Diagram przypadków użycia ====== {{:pl:dydaktyka:ztb:2010:projekty:menadzer_szkolen:przypadki_uzycia.gif|}} \\ ====== Diagram klas ====== {{:pl:dydaktyka:ztb:2010:projekty:menadzer_szkolen:classdiagram.gif|}} \\ ====== Diagramy sekwencji ====== \\ ===== Przeprowadzenie szkolenia ===== {{:pl:dydaktyka:ztb:2010:projekty:menadzer_szkolen:diagram_sekwencji.gif|}}