System Zarządzania Relacjami z Dostawcami (Supplier Relationship Management)
| Parametr | Wartość |
|---|---|
| Wersja dokumentu | 1.0 |
| Data utworzenia | 28 grudnia 2025 |
| Platforma docelowa | .NET 10 |
| Typ aplikacji | WPF (Windows Presentation Foundation) |
| Baza danych | SQLite |
| Wzorzec architektoniczny | MVVM |
| Repozytorium | https://github.com/WoofDeveloper/SupplyManagerSRM |
- Wprowadzenie
- Wymagania systemowe
- Architektura aplikacji
- Struktura projektu
- Warstwa danych (Models)
- Warstwa dostępu do danych (Data)
- Warstwa prezentacji (ViewModels)
- Interfejs użytkownika (Views)
- Funkcjonalności aplikacji
- Przepływ danych
- Instrukcja instalacji i uruchomienia
- Rozwiązywanie problemów
- Możliwości rozwoju
SupplyManagerSRM to desktopowa aplikacja WPF służąca do kompleksowego zarządzania bazą dostawców oraz ich ofertami produktowymi. System umożliwia:
- Ewidencjonowanie dostawców wraz z danymi kontaktowymi
- Zarządzanie ofertami cenowymi produktów
- Śledzenie czasów realizacji zamówień
- Filtrowanie i wyszukiwanie dostawców
- Przechowywanie informacji o preferencjach płatniczych
Aplikacja przeznaczona jest dla:
- Działów zakupów w firmach produkcyjnych
- Małych i średnich przedsiębiorstw handlowych
- Specjalistów ds. zaopatrzenia
- Osób zarządzających relacjami z dostawcami
| Komponent | Technologia |
|---|---|
| Framework | .NET 10 |
| UI | WPF (Windows Presentation Foundation) |
| ORM | Entity Framework Core |
| Baza danych | SQLite |
| MVVM Toolkit | CommunityToolkit.Mvvm |
| Język | C# 14.0 |
| Parametr | Minimum | Zalecane |
|---|---|---|
| Procesor | 1 GHz | 2 GHz lub szybszy |
| RAM | 512 MB | 2 GB |
| Dysk | 100 MB | 500 MB |
| Rozdzielczość | 1024x768 | 1280x720 lub wyższa |
- System operacyjny: Windows 10 (wersja 1607+) lub Windows 11
- .NET 10 Runtime lub SDK
- Visual Studio 2022/2026 (do kompilacji)
Aplikacja została zbudowana zgodnie ze wzorcem Model-View-ViewModel (MVVM), który zapewnia:
- Separację odpowiedzialności – logika biznesowa jest oddzielona od interfejsu użytkownika
- Testowalność – ViewModele można testować niezależnie od widoków
- Łatwość utrzymania – zmiany w UI nie wpływają na logikę biznesową
- Powiązanie danych (Data Binding) – automatyczna synchronizacja między widokiem a danymi
VIEW (MainWindow.xaml)
│
└── Data Binding
│
▼
VIEWMODEL (MainViewModel)
│
└── Wywołania serwisu
│
▼
SERVICE (SupplierService)
│
└── Entity Framework Core
│
▼
MODEL (AppDbContext + Entities)
│
└──
│
▼
DATABASE (SQLite: supply_manager.db)
SupplyManagerSRM/
│
├── Data/
│ ├── AppDbContext.cs
│ ├── ISupplierService.cs
│ └── SupplierService.cs
│
├── Models/
│ ├── Supplier.cs
│ └── ProductOffer.cs
│
├── ViewModels/
│ ├── Main/
│ │ └── MainViewModel.cs
│ ├── ProductOffer/
│ │ ├── ProductOfferEditViewModel.cs
│ │ └── ProductOfferViewModel.cs
│ └── Supplier/
│ ├── SupplierEditViewModel.cs
│ └── SupplierViewModel.cs
│
├── Views/
│ ├── MainWindow.xaml
│ └── MainWindow.xaml.cs
│
├── App.xaml
├── App.xaml.cs
├── SupplyManagerSRM.csproj
└── supply_manager.db
Plik: Models/Supplier.cs
public class Supplier
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Address { get; set; } = string.Empty;
public bool IsInvoiceElectronic { get; set; }
public string PaymentMethod { get; set; } = "Przelew";
public virtual ICollection<ProductOffer> ProductOffers { get; set; } = new List<ProductOffer>();
}Opis pól:
| Pole | Typ | Opis | Wartość domyślna |
|---|---|---|---|
| Id | int | Klucz główny (PK), auto-increment | - |
| Name | string | Nazwa firmy dostawcy | "" |
| Address | string | Adres siedziby | "" |
| IsInvoiceElectronic | bool | Czy akceptuje e-faktury | false |
| PaymentMethod | string | Preferowana metoda płatności | "Przelew" |
| ProductOffers | ICollection | Kolekcja ofert (relacja 1:N) | new List<>() |
Plik: Models/ProductOffer.cs
public class ProductOffer
{
public int Id { get; set; }
public string ProductName { get; set; } = string.Empty;
public decimal Price { get; set; }
public int LeadTimeDays { get; set; }
public int SupplierId { get; set; }
public virtual Supplier? Supplier { get; set; }
}Opis pól:
| Pole | Typ | Opis | Wartość domyślna |
|---|---|---|---|
| Id | int | Klucz główny (PK), auto-increment | - |
| ProductName | string | Nazwa produktu | "" |
| Price | decimal | Cena jednostkowa | 0 |
| LeadTimeDays | int | Czas realizacji w dniach | 0 |
| SupplierId | int | Klucz obcy (FK) do Supplier | - |
| Supplier | Supplier? | Właściwość nawigacyjna | null |
- Supplier → ProductOffer: relacja jeden-do-wielu (1:N)
- Jeden dostawca może mieć wiele ofert produktowych
- Każda oferta należy do dokładnie jednego dostawcy
Plik: Data/AppDbContext.cs
public class AppDbContext : DbContext
{
public DbSet<Supplier> Suppliers { get; set; }
public DbSet<ProductOffer> ProductOffers { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Data Source=supply_manager.db");
}
}Plik: Data/ISupplierService.cs
public interface ISupplierService
{
Task<List<Supplier>> GetSuppliersAsync();
Task AddSupplierAsync(Supplier supplier);
Task DeleteSupplierAsync(int supplierId);
Task<List<Supplier>> SearchSuppliersAsync(string searchText);
Task<List<ProductOffer>> GetProductOffersForSupplierAsync(int supplierId);
Task AddProductOfferAsync(ProductOffer offer);
Task DeleteProductOfferAsync(int offerId);
}Plik: Data/SupplierService.cs
| Metoda | Opis | Parametry | Zwraca |
|---|---|---|---|
| GetSuppliersAsync() | Pobiera wszystkich dostawców z ofertami | - | List |
| AddSupplierAsync() | Dodaje nowego dostawcę | Supplier supplier | Task |
| DeleteSupplierAsync() | Usuwa dostawcę i jego oferty | int supplierId | Task |
| SearchSuppliersAsync() | Wyszukuje dostawców po nazwie | string searchText | List |
| GetProductOffersForSupplierAsync() | Pobiera oferty dostawcy | int supplierId | List |
| AddProductOfferAsync() | Dodaje ofertę produktową | ProductOffer offer | Task |
| DeleteProductOfferAsync() | Usuwa ofertę | int offerId | Task |
Plik: ViewModels/Main/MainViewModel.cs
Główny ViewModel aplikacji, zarządzający całym stanem interfejsu użytkownika.
| Właściwość | Typ | Opis |
|---|---|---|
| Title | string | Tytuł okna aplikacji |
| Suppliers | ObservableCollection | Lista dostawców |
| SelectedSupplierOffers | ObservableCollection | Oferty wybranego dostawcy |
| SelectedSupplier | SupplierViewModel? | Aktualnie wybrany dostawca |
| SelectedProductOffer | ProductOfferViewModel? | Aktualnie wybrana oferta |
| PaymentMethods | ObservableCollection | Dostępne metody płatności |
| SearchText | string | Tekst wyszukiwania |
| Właściwość | Typ | Opis |
|---|---|---|
| SupplierEditor | SupplierEditViewModel | Dane formularza dostawcy |
| OfferEditor | ProductOfferEditViewModel | Dane formularza oferty |
| Komenda | Opis |
|---|---|
| ZaladujDostawcowAsyncCommand | Ładuje listę dostawców |
| DodajDostawceAsyncCommand | Dodaje nowego dostawcę |
| UsunDostawceAsyncCommand | Usuwa wybranego dostawcę |
| FiltrujDostawcowAsyncCommand | Filtruje dostawców |
| DodajOferteAsyncCommand | Dodaje nową ofertę |
| UsunOferteAsyncCommand | Usuwa wybraną ofertę |
Plik: ViewModels/Supplier/SupplierViewModel.cs
Wrapper dla modelu Supplier, implementujący INotifyPropertyChanged.
Plik: ViewModels/Supplier/SupplierEditViewModel.cs
ViewModel dla formularza edycji dostawcy.
Analogiczne ViewModele dla ofert produktowych.
Okno główne jest podzielone na dwie kolumny:
Lewa kolumna (Dostawcy):
- Formularz dodawania dostawcy
- Wyszukiwarka dostawców
- Lista dostawców (DataGrid)
- Przycisk usuwania dostawcy
Prawa kolumna (Oferty):
- Lista ofert wybranego dostawcy (DataGrid)
- Formularz dodawania oferty
- Przycisk usuwania oferty
| Komponent | Typ | Powiązanie (Binding) |
|---|---|---|
| Tytuł okna | Window.Title | {Binding Title} |
| Lista dostawców | DataGrid | {Binding Suppliers} |
| Zaznaczony dostawca | DataGrid.SelectedItem | {Binding SelectedSupplier} |
| Wyszukiwarka | TextBox | {Binding SearchText} |
| Metody płatności | ComboBox | {Binding PaymentMethods} |
| Lista ofert | DataGrid | {Binding SelectedSupplierOffers} |
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel(new SupplierService());
}
}| Funkcja | Opis | Walidacja |
|---|---|---|
| Dodawanie | Tworzenie nowego dostawcy | Nazwa nie może być pusta |
| Wyświetlanie | Lista wszystkich dostawców | - |
| Wyszukiwanie | Filtrowanie po nazwie | - |
| Usuwanie | Usunięcie dostawcy i jego ofert | Potwierdzenie użytkownika |
| Funkcja | Opis | Walidacja |
|---|---|---|
| Dodawanie | Tworzenie oferty dla dostawcy | Wybrany dostawca, nazwa niepusta, cena > 0, dni > 0 |
| Wyświetlanie | Lista ofert wybranego dostawcy | - |
| Usuwanie | Usunięcie oferty | Potwierdzenie użytkownika |
Dostawca:
- Nazwa: wymagana, niepusta
Oferta:
- Dostawca: wymagany (musi być zaznaczony)
- Nazwa produktu: wymagana, niepusta
- Cena: wymagana, > 0
- Czas realizacji: wymagany, > 0
App.OnStartup()tworzy bazę danych (jeśli nie istnieje)MainWindowinicjalizujeMainViewModelzSupplierServiceMainViewModelautomatycznie ładuje listę dostawców
- Użytkownik wypełnia formularz (pola bindowane do
SupplierEditor.*) - Kliknięcie "Dodaj dostawcę" wywołuje
DodajDostawceAsyncCommand - Walidacja danych
- Zapis do bazy przez
SupplierService - Czyszczenie formularza
- Odświeżenie listy dostawców
- Kliknięcie wiersza w DataGrid ustawia
SelectedSupplier OnSelectedSupplierChanged()wywołujeZaladujOfertyAsync()- Lista ofert zostaje zaktualizowana
git clone https://github.com/WoofDeveloper/SupplyManagerSRM.git
cd SupplyManagerSRMVisual Studio:
- Otwórz
SupplyManagerSRM.sln - Ustaw
SupplyManagerSRMjako projekt startowy - Naciśnij
F5lub wybierz Debug > Start Debugging
CLI (.NET):
dotnet restore
dotnet build
dotnet run --project SupplyManagerSRMPrzy pierwszym uruchomieniu aplikacja automatycznie:
- Tworzy plik bazy danych
supply_manager.db - Generuje schemat tabel (Suppliers, ProductOffers)
- Wyświetla pustą listę dostawców
Objaw:
System.Windows.Data Error: 40 : BindingExpression path error
Rozwiązanie:
- Sprawdź, czy
DataContextjest poprawnie ustawiony - Zweryfikuj nazwy właściwości w XAML i ViewModelu
- Upewnij się, że właściwości są publiczne
Objaw: Aplikacja nie zapisuje danych
Rozwiązanie:
- Sprawdź uprawnienia do zapisu w katalogu aplikacji
- Zweryfikuj connection string w
AppDbContext - Usuń plik
supply_manager.dbi uruchom ponownie
Objaw: Przyciski nie reagują na kliknięcia
Rozwiązanie:
- Sprawdź, czy komendy są poprawnie zainicjalizowane w konstruktorze
- Zweryfikuj bindingi
Commandw XAML - Upewnij się, że metody komend są
async Task
- Edycja istniejących dostawców
- Edycja ofert produktowych
- Eksport danych do Excel/CSV
- Raportowanie i statystyki
- Historia zmian (audyt)
- Wielojęzyczność (i18n)
- Dependency Injection (Microsoft.Extensions.DependencyInjection)
- Logging (Serilog / NLog)
- Testy jednostkowe (xUnit / NUnit)
- Testy UI (Selenium / WinAppDriver)
- CI/CD (GitHub Actions)
WoofDeveloper
- GitHub: github.com/WoofDeveloper
- Repozytorium: SupplyManagerSRM
Ten projekt jest udostępniony na licencji MIT.
MIT License
Copyright (c) 2025 WoofDeveloper
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.