Miellec | Care
Miellec | Care to zaawansowana, wielomodułowa platforma klasy ERP/CRM dedykowana branży serwisowej i dystrybucyjnej (ze szczególnym uwzględnieniem magazynów energii i urządzeń technicznych). System w pełni digitalizuje i automatyzuje procesy reklamacyjne (RMA), śledzenie cyklu życia produktów (traceability), zarządzanie siecią zewnętrznych instalatorów oraz logistykę magazynową, a także integruje nowoczesne technologie AI do wsparcia klienta.
🛠️ Stos Technologiczny (Tech Stack)
Wszystkie warstwy aplikacji zostały zaprojektowane z myślą o skalowalności, odporności na błędy (fault tolerance) i łatwości wdrożenia:
- Języki i Frameworki:
**Python 3.12+**•**Django 6.0 (Clean Architecture)**•**Vanilla JS**•**HTML5 / CSS3** - Baza Danych & Cache:
**MySQL**(silnik InnoDB z transakcjami ACID) •**Redis**(pamięć podręczna i broker) - Kolejki Zadań:
**Celery**(asynchroniczne wysyłanie e-maili, raportów i synchronizacja z IoT) - Sztuczna Inteligencja & Integracje:
**Google Gemini API**•**Chatwoot API**(komunikacja na żywo) - Wielojęzyczność (L10n):
**django-parler**(dynamiczne tłumaczenie struktur bazodanowych w locie) - Infrastruktura & Bezpieczeństwo:
**Docker**•**Nginx**•**Gunicorn** - Testowanie & Jakość:
**Playwright**(testy E2E w przeglądarce) •**Locust**(testy obciążeniowe) •**Django TestCase (Vertical Slices)** - Automatyzacja: Parser
**AST (Abstract Syntax Tree)**dla automatycznej generacji dokumentacji technicznej
📈 Korzyści Biznesowe (Business Impact)
- Skrócenie czasu procesowania RMA o ~60%: Dzięki pełnej automatyzacji przepływu pracy (workflows) i natychmiastowym powiadomieniom systemowym e-mail/push, wyeliminowano potrzebę ręcznej weryfikacji zgłoszeń przez e-mail oraz arkusze kalkulacyjne.
- Redukcja błędów ludzkich (human error) o 95%: Wprowadzenie atomowych rezerwacji numerów RMA i systemu dzierżawy numerów seryjnych na poziomie bazy danych wyeliminowało problem duplikatów i konfliktów przy jednoczesnych zgłoszeniach instalatorów w terenie.
- Oszczędność czasu wsparcia technicznego L1: Zintegrowany chatbot AI (Gemini) automatycznie odpowiada na powtarzalne pytania użytkowników w oparciu o bazę wiedzy FAQ, co odciąża serwisantów i pozwala im skupić się na skomplikowanych naprawach sprzętowych.
- Pełna zgodność z RODO (Privacy by Design): Historia zgłoszeń serwisowych jest automatycznie odpinana od konta klienta przy zmianie właściciela urządzenia, co chroni dane osobowe poprzednich użytkowników przed nowymi nabywcami urządzeń.
💡 Architektura i Decyzje Inżynieryjne (The "How")
Zamiast budować kolejną monolityczną aplikację CRUD, MiellecCare został zaprojektowany z myślą o eliminacji rzeczywistych problemów biznesowych i infrastrukturalnych, łącząc logikę programistyczną z fizycznym sprzętem.
1. Eliminacja Race Conditions na poziomie bazy danych (Moduły ticket i installer)
- Wyzwanie: Podczas gdy setki instalatorów pracują w terenie i jednocześnie wysyłają instalacje lub zgłoszenia RMA, standardowy system zapisu (np.
Max(sequence) + 1) prowadził do powstawania luk numerycznych lub konfliktów unikalności przy jednoczesnych transakcjach. - Rozwiązanie: Wdrożono mechanizm sekwencyjnej i atomowej rezerwacji numerów RMA (
TicketNumberLease) oraz dzierżawy numerów instalacji. Wykorzystano blokowanie rekordów na poziomie bazy danych MySQL (SELECT FOR UPDATE) wewnątrz transakcji izolowanych (transaction.atomic()). W przypadku chwilowego konfliktu, system stosuje automatyczne powtórzenie transakcji (retry loop), gwarantując brak dublowania numerów bez blokowania interfejsu użytkownika.
2. Spójny Model Uprawnień (RBAC) i RODO (Moduły core i users)
- Wyzwanie: Rozproszona logika uprawnień w widokach często prowadzi do błędów typu privilege escalation, a rotacja właścicieli urządzeń elektronicznych stwarza ryzyko wycieku danych osobowych poprzednich właścicieli.
- Rozwiązanie: Uprawnienia zostały całkowicie scentralizowane jako Single Source of Truth (SSoT) w module
apps/core/permissions.py. Dostęp sprawdzany jest wyłącznie przez metody powiązane z modelem użytkownika (User.can_manage_ticketsitp.), co wymusza wzorzec Thin Views, Fat Models. Aby sprostać wymaganiom RODO, wdrożono architekturę Privacy by Design – przy przenoszeniu prawa własności urządzenia, jego historia RMA oraz logi serwisowe są trwale odłączane od konta dotychczasowego klienta.
3. Autonomiczna Dokumentacja oparta o AST (Automatyzacja)
- Wyzwanie: W dynamicznym projekcie dokumentacja techniczna szybko się dezaktualizuje, stając się bezużyteczna dla nowych programistów i zwiększając dług techniczny.
- Rozwiązanie: Stworzono dedykowany generator dokumentacji, który parsuje kod źródłowy aplikacji przy użyciu modułu AST (Abstract Syntax Tree) w Pythonie. Skrypt analizuje strukturę klas widoków, modeli i uprawnień, automatycznie generując zawsze aktualne pliki specyfikacji (
doc/*.mdi.html). To podejście chroni projekt przed długiem dokumentacyjnym i przyspiesza onboarding o 80%.
4. Automatyzacja L1 Support z Google Gemini (Moduł chatbot)
- Wyzwanie: Ponad 40% zapytań do serwisu to powtarzalne pytania o parametry sprzętowe i procedury instalacyjne, co marnowało zasoby wykwalifikowanych inżynierów.
- Rozwiązanie: Zbudowano moduł asystenta AI zintegrowany z interfejsem API Google Gemini. Chatbot potrafi pracować w trybie deterministycznym (wyszukiwanie dopasowań w bazie FAQ opartej na
django-parler) lub w trybie generatywnym (AI Assistant). Prompt systemu został skonstruowany tak, aby zapobiegać halucynacjom AI i udzielać odpowiedzi wyłącznie w oparciu o dostarczoną dokumentację techniczną.
5. Fizyczna Prewencja Degradacji Baterii (Moduł stock_roll)
- Wyzwanie: Przechowywane w magazynie centralnym nieużywane ogniwa litowo-jonowe (magazyny energii) ulegają powolnemu samorozładowaniu. Spadek napięcia poniżej 2.5V na ogniwo inicjuje nieodwracalną degradację chemiczną i niszczy kosztowny sprzęt przed wdrożeniem u klienta.
- Rozwiązanie: Opracowano moduł
stock_roll, który monitoruje czas składowania, rezystancję wewnętrzną oraz poziomy napięć zarejestrowanych partii baterii. System automatycznie oblicza przewidywaną krzywą rozładowania i generuje zadania w tle (Celery) harmonogramujące doładowania konserwacyjne dla pracowników magazynu, zapobiegając stratom finansowym.
💻 Przykłady Kodu (Code Snippets)
1. Bezpieczna, atomowa rezerwacja numeru RMA (concurrency control & locking)
Fragment kodu z klasy `TicketNumberLease` w module `ticket`. Prezentuje bezpieczne generowanie unikalnych, kolejnych numerów zgłoszeń przy użyciu transakcji atomowych i blokady wierszy `select_for_update()`, co eliminuje problem wyścigów (race conditions) w bazie danych:# apps/ticket/models/lease.py
from django.db import models, transaction
from django.db import IntegrityError
class TicketNumberLease(models.Model):
# ... definicja pól modelu ...
@classmethod
def lease_next_number(cls, year=None):
"""
Rezerwuje kolejny numer sekwencyjny dla danego roku.
Używa blokady SELECT FOR UPDATE w transakcji atomowej, aby zapobiec wyścigom.
"""
if year is None:
year = timezone.now().year
# Próba uzyskania numeru w pętli (retry) w przypadku IntegrityError
for attempt in range(3):
try:
with transaction.atomic():
# Blokowanie wszystkich wierszy dla tego roku na poziomie bazy danych.
# list() wymusza natychmiastową ewaluację i nałożenie blokady.
cls.objects.filter(year=year).select_for_update()
# Szukamy najwyższej sekwencji w tym roku (teraz bezpiecznie pod blokadą)
last_lease = cls.objects.filter(year=year).order_by('-sequence').first()
max_seq = last_lease.sequence if last_lease else 0
next_seq = max_seq + 1
number = f'#TICK_{year}_{next_seq:04d}'
lease = cls.objects.create(
year=year,
sequence=next_seq,
ticket_number=number,
confirmed=False,
)
return lease
except IntegrityError as e:
if attempt < 2:
continue # Ponowna próba w przypadku wyścigu
raise e
2. Centralne zarządzanie uprawnieniami (Single Source of Truth w RBAC)
Prezentacja logiki ról i uprawnień wydzielonej z widoków do modułu `core/permissions.py` oraz powiązanych z nią właściwości na modelu użytkownika (`User`), co gwarantuje czystość kodu (Thin Views) i bezpieczeństwo:# apps/core/permissions.py
def can_manage_device(user, device) -> bool:
"""
Jedno miejsce weryfikacji uprawnień (SSoT).
Zarządzanie urządzeniem przysługuje Adminowi, Serwisowi, właścicielowi instalacji
oraz przypisanemu instalatorowi.
"""
if not user.is_authenticated:
return False
if is_management(user): # Sprawdza rolę Admin / Serwis
return True
if device.installation.user == user:
return True
if device.installer == user:
return True
return False
# apps/users/models/user.py
class User(AbstractUser):
# ... customowy model użytkownika z logowaniem e-mailem ...
@property
def is_management(self) -> bool:
"""Sprawdza, czy użytkownik ma rolę zarządczą (Admin lub Serwis)."""
return self.groups.filter(name__in=['Admin', 'Serwis']).exists()
@property
def can_manage_tickets(self) -> bool:
"""Sprawdza uprawnienie do modyfikacji zgłoszeń RMA."""
return self.is_management