# Zasady modyfikacji plików core Dolibarr

Obowiązują przy każdej edycji pliku należącego do rdzenia Dolibarr
(czyli wszystko poza `htdocs/custom/`).

## Procedura

1. **WYMAGANA ZGODA** — nigdy nie modyfikuj żadnego pliku core Dolibarr bez wcześniejszej, wyraźnej zgody użytkownika. Zaproponuj zmianę, opisz co i dlaczego chcesz zmodyfikować, i **czekaj na potwierdzenie** przed wykonaniem jakiejkolwiek edycji.

2. **Sprawdź czy istnieje kopia `.org`** obok pliku docelowego.
   - Przykład: chcesz edytować `htdocs/core/lib/functions.lib.php`  
     → sprawdź czy istnieje `htdocs/core/lib/functions.lib.php.org`

3. **Jeśli `.org` ISTNIEJE** — plik był już wcześniej modyfikowany.  
   Możesz swobodnie wprowadzać zmiany w `.php`.

4. **Jeśli `.org` NIE ISTNIEJE** — plik jest nienaruszony.  
   Przed pierwszą zmianą utwórz kopię:
   ```
   cp plik.php plik.php.org
   ```
   Następnie edytuj `.php`.

   **Jeśli wystąpi błąd dostępu** (np. `Permission denied`):
   - Po **pierwszym** niepowodzeniu **zapytaj użytkownika o nadanie dostępu** do pliku
   - Jeżeli plik należy do `root` — poproś o wykonanie `sudo chmod` lub `sudo chown` przez użytkownika
   - **Nie próbuj `sudo` samodzielnie** — czekaj na potwierdzenie
   - Dopiero po potwierdzeniu kontynuuj tworzenie `.org`

5. **Po każdej zmianie** — zaktualizuj kopię `.patch` (snapshot bieżącego stanu pliku po modyfikacji):
   ```
   cp plik.php plik.php.patch
   ```
   `.patch` zawsze odzwierciedla **aktualny stan po zmianach** — nadpisuj go przy każdej kolejnej edycji.

## Cel

- `.org` = oryginał z dystrybucji Dolibarr (punkt odniesienia do diffów i rollbacku)
- `.patch` = bieżąca wersja po naszych zmianach (snapshot do szybkiego przywrócenia / porównania)
- Umożliwia łatwe porównanie `diff plik.php.org plik.php.patch` — widać dokładnie co zostało zmienione
- Nigdy nie modyfikuj `.org` — to tylko kopia bezpieczeństwa

## Zakres

Dotyczy **każdego** pliku poza `htdocs/custom/`:
- `htdocs/core/`
- `htdocs/compta/`, `htdocs/societe/`, `htdocs/product/` itp.
- `htdocs/*.php` (np. `main.inc.php`, `master.inc.php`)
- szablony, klasy, biblioteki — wszystko co nie jest modułem custom

## Aktualnie zmodyfikowane pliki core

### mrp/class/mo.class.php
- **Zmiana:** Pre-populate operation tracking at MO validation
- **Powód:** Transfer step_order from productionrules to MO operation rank
- **Lokalizacja:** `Mo::validate()` po triggers, przed oldref assignment
- **Mechanizm:** Skeleton entries (qty_delta=0) z MIN(position) per workstation
- **Backup:** `.org` + `.patch` maintained

### mrp/class/mooptracking.class.php
- **Zmiana:** Read op_rank from optracking table instead of calculating from position
- **Powód:** Support pre-populated rank values from BOM step_order
- **Lokalizacja:** `MoOpTracking::getOperationsFromMo()` po sortowaniu seen array
- **Mechanizm:** DISTINCT query na mrp_mo_optracking, fallback do min_position
- **Backup:** `.org` + `.patch` maintained

### mrp/mo_card.php
- **Zmiana 1:** Fix MO label generation — qty suffix `x10` nie był obcinany do `x1`
- **Powód:** `rtrim(rtrim((string)$qty, '0'), '.')` obcinało znaczące zera z liczb całkowitych (10→1, 20→2)
- **Lokalizacja:** Blok pre-fill label z `prod_mo_material_overrides` (~linia 146)
- **Mechanizm:** Zastosowanie rtrim tylko gdy wartość zawiera kropkę dziesiętną; dla liczb całkowitych rzutowanie `(int)`
- **Zmiana 2:** Fix usuwanie danych BOM przy delete MO — po usunięciu MO nie można było ponownie stworzyć MO z tego samego BOM-a
- **Powód:** Blok `confirm_delete` kasował `prod_bom_mo_qty` i `prod_mo_material_overrides` powiązane z `fk_bom`, choć BOM nadal istniał
- **Lokalizacja:** Handler `confirm_delete` (~linia 281)
- **Mechanizm:** Usunięcie obu DELETE-ów BOM-level; cleanup pozostaje wyłącznie w `bom_card.php`
- **Zmiana 3:** Cleanup planning module records przy delete MO
- **Powód:** `planning_schedule` i `planning_job` zawierają `fk_mo` — bez cleanup pozostają osierocone rekordy
- **Lokalizacja:** Handler `confirm_delete`, po DELETE `mrp_mo_optracking`
- **Mechanizm:** DELETE `planning_schedule` + `planning_job` WHERE `fk_mo`
- **Backup:** `.org` + `.patch` maintained

### bom/class/bom.class.php
- **Zmiana:** Cleanup productionrules tables w metodzie `BOM::delete()`
- **Powód:** Bulk delete z `bom_list.php` wywołuje `delete()` bezpośrednio — cleanup w `bom_card.php` był pomijany
- **Lokalizacja:** `BOM::delete()` przed wywołaniem `deleteCommon()`
- **Mechanizm:** DELETE `prod_bom_mo_qty` + `prod_mo_material_overrides` WHERE `fk_bom`; obejmuje każdą ścieżkę usuwania BOM-a
- **Backup:** `.org` + `.patch` maintained

### mrp/mo_production.php
- **Zmiana:** Sort consumption lines with materials first, then services
- **Powód:** Display materials before services in consumption section
- **Lokalizacja:** Before consumption loop (~line 1217)
- **Mechanizm:** Custom usort by position range (>= 1000 = material, < 1000 = service)
- **Backup:** `.org` + `.patch` maintained

### core/menus/standard/eldy.lib.php
- **Zmiana 1:** Ukrycie wyszarzonych pozycji top navbar (showmode=2) zamiast ich wyświetlania
- **Powód:** Operatorzy bez uprawnień nie widzą żadnych pozycji top menu
- **Lokalizacja:** Pętla `foreach ($menu->liste as $menuval)` w `print_top_menu_entry()`
- **Mechanizm:** `if ($menuval['enabled'] == 2) continue;`
- **Zmiana 2:** Ukrycie wyszarzonych pozycji left menu (level 0 i level >0)
- **Powód:** Spójne z top menu — pozycje bez uprawnień całkowicie niewidoczne
- **Lokalizacja:** Bloki renderowania level=0 i level>0 w `print_left_eldy_menu()`
- **Mechanizm:** Usunięto bloki `elseif ($showmenu)` renderujące `vmenudisabled`; `menu_top` renderowany tylko gdy `$lastlevel0 == 'enabled'`
- **Zmiana 3:** Fix uprawnienia dla "Variant Attributes" w left menu Products i Services
- **Powód:** Menu sprawdzało `product.read`/`service.read`, a strona `variants/list.php` wymaga `variants.read` — operator widział link ale dostawał Access denied
- **Lokalizacja:** `get_left_menu_products()` — dwa wywołania `$newmenu->add("/variants/list.php"...)`
- **Mechanizm:** Zmiana warunku z `$user->hasRight('product', 'read')` / `$user->hasRight('service', 'read')` na `$user->hasRight('variants', 'read')`
- **Zmiana 4:** Ukrycie pozycji top menu "Tools" dla operatorów z ograniczonym dostępem
- **Powód:** Email templates, BI Custom Reports i API Explorer widoczne dla operatorów bez potrzeby
- **Lokalizacja:** `print_eldy_menu()` — blok `$tmpentry` dla Tools (~linia 441)
- **Mechanizm:** Zmiana `'perms' => '1'` na `'perms' => '(empty($conf->global->MAIN_USE_ADVANCED_PERMS) || !empty($user->admin))'`
- **Backup:** `.org` + `.patch` maintained

### core/lib/product.lib.php
- **Zmiana:** Ukrycie zakładek "Selling prices" i "Buying prices" zamiast wyświetlania ich jako disabled
- **Powód:** Operatorzy z `MAIN_USE_ADVANCED_PERMS` bez uprawnień `read_prices`/`read_supplier_prices` nie widzą zakładek wcale
- **Lokalizacja:** `product_prepare_head()` — usunięto bloki `else` dla obu zakładek cenowych
- **Mechanizm:** Gdy `$usercancreadprice` lub `$usercancreadsupplierprice` = false, zakładka nie jest dodawana do `$head[]`
- **Backup:** `.org` + `.patch` maintained

### main.inc.php
- **Zmiana:** Ukrycie ikon Module Builder i Drukarka w top nav bar dla operatorów z ograniczonym dostępem
- **Powód:** Operatorzy z `MAIN_USE_ADVANCED_PERMS` nie powinni widzieć narzędzi developerskich ani przycisku druku
- **Lokalizacja:** Funkcja `top_menu()` — warunki renderowania bloków `modulebuilder` i `fa-print`
- **Mechanizm:** Dodanie warunku `(empty($conf->global->MAIN_USE_ADVANCED_PERMS) || !empty($user->admin))` do obu bloków
- **Backup:** `.org` + `.patch` maintained

## Aktualizacje core (źródło i wdrożenie)

- Core Dolibarr w tym środowisku **nie jest utrzymywany jako lokalne repo Git**.
- Nowe wersje core pochodzą z oficjalnej paczki GitHub (`.tgz`).
- Każdy update najpierw jest kopiowany i testowany na środowisku `dolibarr-dev/`.
- Dopiero po zatwierdzeniu testów zmiany są kopiowane na środowisko `dolibarr/`.
- Po zatwierdzeniu update należy uruchomić `custom/dolibarr_patch_update.sh`, aby automatycznie odtworzyć lokalne poprawki core na podstawie par `.org` / `.patch`.
- Przy pracy nad core zawsze zakładaj, że lokalne zmiany mogą zostać nadpisane przez kolejny update z paczki.
