454 lines
21 KiB
Markdown
454 lines
21 KiB
Markdown
# HANDEL14 — Płatności dokumentu handlowego
|
|
|
|
> Wspólne fakty o typie, podstawowe typy i szablon wzorca: [../handel.md](../handel.md).
|
|
|
|
Płatności (należności i zobowiązania) powstają automatycznie z dokumentu handlowego płatnego (np. FV, FZ)
|
|
i opisują kwoty do uregulowania: termin, sposób zapłaty, ewidencję środków pieniężnych (ŚP) oraz stan
|
|
rozliczenia z zapłatami. Z poziomu dokumentu dostęp do nich daje kolekcja `dok.Platnosci`
|
|
(`SubTable<Soneta.Kasa.Platnosc>`). Pojedyncza płatność to obiekt `Soneta.Kasa.Platnosc` — w praktyce jedna
|
|
z dwóch klas konkretnych: `Naleznosc` (kierunek `Przychod`, sprzedaż) lub `Zobowiazanie` (kierunek
|
|
`Rozchod`, zakup). Wymagana referencja do `Soneta.Kasa`.
|
|
|
|
> **Pojęcia.** Kwota płatności (`Kwota: Currency`) jest w walucie dokumentu; `KwotaKsiegi: Currency` to jej
|
|
> przeliczenie na PLN po `Kurs`. Stan uregulowania to `StanRozliczenia` (+ `KwotaRozliczona`,
|
|
> `DoRozliczenia`). Płatności są edytowalne wyłącznie, gdy dokument (i sama płatność) są w **buforze** —
|
|
> po zatwierdzeniu pola płatności stają się tylko do odczytu.
|
|
|
|
---
|
|
|
|
### HANDEL-W75 — Przeglądanie płatności dokumentu
|
|
|
|
**Cel:** odczytać płatności wystawione z dokumentu — kwotę, walutę, sposób zapłaty, termin oraz stan
|
|
rozliczenia — bez modyfikacji.
|
|
|
|
**Warianty:**
|
|
|
|
| Wariant | Źródło / pole |
|
|
|---|---|
|
|
| Lista płatności dokumentu | `dok.Platnosci` (`SubTable<Platnosc>`) |
|
|
| Kwota i waluta | `p.Kwota: Currency` (`.Value`, `.Symbol`) |
|
|
| Sposób zapłaty | `p.SposobZaplaty: Soneta.Kasa.SposobZaplaty` (`.Nazwa`, `.Typ`, `.MPP`) |
|
|
| Termin płatności | `p.Termin: Date`, `p.TerminDni: int` (dni od daty odniesienia) |
|
|
| Stan rozliczenia | `p.StanRozliczenia`, `p.Rozliczono: bool`, `p.KwotaRozliczona`, `p.DoRozliczenia` |
|
|
| Kwota nierozliczona po terminie | `p.DoRozliczenia` + warunek `p.Termin < Date.Today` |
|
|
| Należność / zobowiązanie | `p.Kierunek`, `p.CzyNaleznosc: bool`, `p.CzyZobowiazanie: bool` |
|
|
|
|
**Pola i typy:** `Platnosc.Kwota: Soneta.Types.Currency`, `KwotaKsiegi: Currency` (PLN),
|
|
`SposobZaplaty: Soneta.Kasa.SposobZaplaty`, `Termin: Soneta.Types.Date`, `TerminDni: int`,
|
|
`StanRozliczenia: Soneta.Kasa.StanRozliczenia` (`Nierozliczony=0`, `Czesciowo=1`, `Calkowicie=2`,
|
|
`NiePodlega=3`), `Rozliczono: bool`, `KwotaRozliczona: Currency`, `DoRozliczenia: Currency`,
|
|
`Kierunek: Soneta.Kasa.KierunekPlatnosci`, `EwidencjaSP: Soneta.Kasa.EwidencjaSP`.
|
|
|
|
**Snippet:**
|
|
|
|
```csharp
|
|
var hm = session.GetHandel();
|
|
var dok = hm.DokHandlowe.WgDaty[...]; // lub inny lookup dokumentu
|
|
|
|
foreach (Platnosc p in dok.Platnosci)
|
|
{
|
|
Currency kwota = p.Kwota; // w walucie dokumentu
|
|
string waluta = p.Kwota.Symbol; // np. "PLN", "EUR"
|
|
string sposob = p.SposobZaplaty.Nazwa; // np. "Przelew", "Gotówka"
|
|
Date termin = p.Termin;
|
|
StanRozliczenia stan = p.StanRozliczenia;
|
|
|
|
// Kwota pozostała do zapłaty i to, co już przeterminowane:
|
|
Currency doZaplaty = p.DoRozliczenia;
|
|
bool poTerminie = !p.Rozliczono && p.Termin < Date.Today && p.DoRozliczenia > Currency.Zero;
|
|
}
|
|
```
|
|
|
|
**Pułapki:**
|
|
- `dok.Platnosci` to `SubTable` — iteruj serwerowo, nie materializuj do `List` tylko po to, by policzyć
|
|
elementy (`IsEmpty`/`Count` są dostępne na kolekcji). Patrz [`rowcondition.md`](references/rowcondition.md).
|
|
- `StanRozliczenia.NiePodlega` oznacza płatność **nierozliczaną** (`p.Rozliczana == false`) — nie myl jej
|
|
z `Nierozliczony` (rozliczana, ale jeszcze niezapłacona).
|
|
- `Kwota` jest w walucie dokumentu; do raportu w PLN użyj `KwotaKsiegi` (HANDEL-W81), nie mnóż „ręcznie".
|
|
- „Po terminie" liczysz z `Termin` i `DoRozliczenia` względem `Date.Today` — w samej płatności nie ma
|
|
gotowego pola „kwota po terminie".
|
|
|
|
---
|
|
|
|
### HANDEL-W76 — Rozbicie płatności na raty
|
|
|
|
**Cel:** zamienić pojedynczą płatność dokumentu na zestaw rat (cyklicznych miesięcznych) albo na rozbicie
|
|
netto + VAT, przy użyciu publicznego workera `PodzialPlatnosciWorker`.
|
|
|
|
**Warianty:**
|
|
|
|
| Wariant | Ustawienie `WParams` |
|
|
|---|---|
|
|
| Raty miesięczne wg liczby rat | `Metoda = WOptions.Raty`, `IlośćRat = n` |
|
|
| Raty miesięczne wg kwoty raty | `Metoda = WOptions.Raty`, `Kwota = kwotaRaty` (worker wyliczy liczbę rat) |
|
|
| Rozbicie netto + VAT (MPP) | `Metoda = WOptions.NettoPlusVat` |
|
|
|
|
**Pola i typy:** worker `Soneta.Handel.PodzialPlatnosci.PodzialPlatnosciWorker`, parametry
|
|
`Soneta.Handel.PodzialPlatnosci.WParams : ContextBase` (inicjowane z `Context` zawierającego
|
|
`DokumentHandlowy`): `Metoda: WOptions` (`NettoPlusVat=0x1`, `Raty=0x2`), `IlośćRat: int`,
|
|
`Kwota: Currency` (kwota pojedynczej raty), `TerminPierwszejWpłaty: Date` (read-only — z warunków
|
|
płatności), `Cykl: WOptions` (`Miesięczny`). Akcja: `PodzielPlatnosci([Context] DokumentHandlowy)`.
|
|
|
|
**Snippet:**
|
|
|
|
```csharp
|
|
// Worker działa na dokumencie w BUFORZE z kierunkiem płatności (FV/FZ).
|
|
// Parametry tworzymy przez Context (wzorzec worker-z-Params), patrz worker-extender.md.
|
|
var context = new Context(session);
|
|
context.Set(dok); // DokumentHandlowy w kontekście
|
|
|
|
var wp = new PodzialPlatnosci.WParams(context)
|
|
{
|
|
Metoda = PodzialPlatnosci.WOptions.Raty,
|
|
IlośćRat = 3, // 3 równe raty miesięczne
|
|
};
|
|
|
|
var worker = new PodzialPlatnosci.PodzialPlatnosciWorker(wp);
|
|
worker.PodzielPlatnosci(dok); // sam otwiera transakcję i robi CommitUI
|
|
|
|
session.Save();
|
|
```
|
|
|
|
**Pułapki:**
|
|
- Akcja jest dostępna tylko gdy `dok.Bufor == true` i `dok.Definicja.KierunekPlatnosci != Brak`
|
|
(`IsVisiblePodzielPlatnosci`) — na zatwierdzonym dokumencie się nie wykona.
|
|
- `PodzielPlatnosci` **sam otwiera transakcję** (`Session.Logout(true)` + `CommitUI`) i **usuwa**
|
|
istniejące płatności dokumentu, zastępując je wyliczonymi ratami/podziałem. Nie zawijaj go w drugą
|
|
transakcję edycyjną; po nim wywołaj `session.Save()`.
|
|
- W trybie `Raty` ustawienie `Kwota` przelicza `IlośćRat` (i odwrotnie) — ustaw jedno z dwóch.
|
|
- Ostatnia rata przejmuje resztę z zaokrągleń (kwoty rat sumują się do `BruttoCy` dokumentu) — nie zakładaj
|
|
równego podziału co do grosza.
|
|
|
|
---
|
|
|
|
### HANDEL-W77 — Ręczne dodanie / edycja pojedynczej płatności
|
|
|
|
**Cel:** ręcznie ułożyć płatności dokumentu — np. część gotówką, resztę przelewem — ustawiając sposób
|
|
zapłaty, ewidencję ŚP, termin i kwotę.
|
|
|
|
**Warianty:**
|
|
|
|
| Wariant | Operacja |
|
|
|---|---|
|
|
| Dodanie należności (sprzedaż) | `new Naleznosc(dok)` + `AddRow` |
|
|
| Dodanie zobowiązania (zakup) | `new Zobowiazanie(dok)` + `AddRow` |
|
|
| Edycja istniejącej | zmiana pól na elemencie `dok.Platnosci` |
|
|
| Częściowo gotówka + przelew | dwie płatności o różnym `SposobZaplaty`, suma `Kwota` = wartość dokumentu |
|
|
|
|
**Pola i typy:** konstruktory `Naleznosc(IDokumentPlatny)`, `Zobowiazanie(IDokumentPlatny)` (publiczne).
|
|
Tabela płatności: `KasaModule.GetInstance(session).Platnosci`. Pola zapisywalne:
|
|
`SposobZaplaty: SposobZaplaty`, `EwidencjaSP: EwidencjaSP`, `Termin: Date` (lub `TerminDni: int`),
|
|
`Kwota: Currency`, `KwotaMPP: Currency`, `Rachunek: RachunekBankowyPodmiotu`, `Priorytet: int`.
|
|
|
|
**Snippet:**
|
|
|
|
```csharp
|
|
var kasa = KasaModule.GetInstance(session);
|
|
var spZaplaty = kasa.SposobyZaplaty;
|
|
|
|
using (var t = session.Logout(editMode: true)) // dokument MUSI być w buforze
|
|
{
|
|
// 1) część gotówką
|
|
var gotowka = new Naleznosc(dok); // sprzedaż -> Naleznosc; zakup -> Zobowiazanie
|
|
kasa.Platnosci.AddRow(gotowka);
|
|
gotowka.SposobZaplaty = spZaplaty.Gotówka;
|
|
gotowka.Kwota = new Currency(300m, "PLN");
|
|
gotowka.Termin = dok.DataDokumentu; // gotówka -> termin = data dokumentu
|
|
|
|
// 2) reszta przelewem
|
|
var przelew = new Naleznosc(dok);
|
|
kasa.Platnosci.AddRow(przelew);
|
|
przelew.SposobZaplaty = spZaplaty.WgNazwy["Przelew"];
|
|
przelew.Kwota = new Currency(dok.BruttoCy.Value - 300m, "PLN");
|
|
przelew.TerminDni = 14; // 14 dni od daty odniesienia
|
|
// przelew.Rachunek = ... // dla przelewu wskaż rachunek podmiotu
|
|
|
|
t.Commit(); // CommitUI() w workerze/extenderze
|
|
}
|
|
session.Save();
|
|
```
|
|
|
|
**Pułapki:**
|
|
- Płatność można dodać **tylko do dokumentu w buforze** — `OnAdded` rzuca wyjątek
|
|
(„Nie można dodawać płatności do zatwierdzonego dokumentu"). `Platnosc.Bufor`/`IsReadOnly` chronią
|
|
edycję po zatwierdzeniu.
|
|
- Dobierz klasę do kierunku dokumentu: sprzedaż (`KierunekPlatnosci.Przychod`) → `Naleznosc`, zakup
|
|
(`Rozchod`) → `Zobowiazanie`. Zła klasa = niespójny kierunek.
|
|
- `Kwota` to `Currency` — twórz `new Currency(wartość, symbolWaluty)`; symbol musi być zgodny z walutą
|
|
dokumentu/ewidencji (weryfikator ostrzega o niezgodności).
|
|
- Dla sposobu zapłaty typu „przelew" wymagany jest `Rachunek` (weryfikator-ostrzeżenie). Ustaw rachunek
|
|
należący do podmiotu płatności (twardy weryfikator `RachunekPodmiotuVerifier`).
|
|
- `SposobZaplaty` pobieraj z tabeli (`kasa.SposobyZaplaty.Gotówka`, `...WgNazwy["Przelew"]`) — to rekord
|
|
konfiguracyjny, nie ustawiaj „z palca".
|
|
|
|
---
|
|
|
|
### HANDEL-W78 — Warunki płatności z kontrahenta i ich przeliczenie na dokumencie
|
|
|
|
**Cel:** odczytać/ustawić warunki płatności dokumentu (sposób, termin w dniach, ewidencja ŚP) spójnie
|
|
z domyślnymi warunkami kontrahenta, przez publiczny `WarunkiPłatnościWorker`.
|
|
|
|
**Warianty:**
|
|
|
|
| Wariant | Mechanizm |
|
|
|---|---|
|
|
| Domyślne warunki z kontrahenta | `Kontrahent.SposobZaplaty`, `Kontrahent.Termin` (HANDEL-W9) — inicjują płatność |
|
|
| Odczyt warunków dokumentu | `WarunkiPłatnościWorker`: `Sposób`, `TerminDni`, `Termin`, `EwidencjaSP`, `Kwota`, `Raty` |
|
|
| Zmiana terminu (w dniach) | `worker.TerminDni = n` lub `worker.Termin = data` |
|
|
| Zmiana sposobu zapłaty | `worker.Sposób = ...` (przelicza też ewidencję ŚP) |
|
|
| Bezpośrednio na płatności | `p.TerminDni`, `p.Termin`, `p.SposobZaplaty`, `p.EwidencjaSP` |
|
|
|
|
**Pola i typy:** worker `Soneta.Kasa.WarunkiPłatnościWorker` (publiczny, zarejestrowany dla
|
|
`IDokumentPlatny`): `[Context] Dokument: IDokumentPlatny`, `TerminDni: int`, `Termin: Date`,
|
|
`Sposób: SposobZaplaty`, `EwidencjaSP: EwidencjaSP`, `Kwota: Currency` (read-only), `Raty: int`
|
|
(liczba płatności). Operuje na **pierwszej** płatności dokumentu. Na kontrahencie:
|
|
`Kontrahent.SposobZaplaty: FormaPlatnosci`, `Kontrahent.Termin: int` (patrz kontrahent HANDEL-W9).
|
|
|
|
**Snippet:**
|
|
|
|
```csharp
|
|
// Warunki płatności kontrahenta są przenoszone na płatność przy jej tworzeniu/zmianie podmiotu.
|
|
// Do odczytu/zmiany "zbiorczej" warunków dokumentu służy WarunkiPłatnościWorker:
|
|
var context = new Context(session);
|
|
context.Set(dok); // dok : IDokumentPlatny (DokumentHandlowy)
|
|
|
|
var warunki = new WarunkiPłatnościWorker { Dokument = dok };
|
|
|
|
int dni = warunki.TerminDni; // termin liczony w dniach
|
|
SposobZaplaty sp = warunki.Sposób;
|
|
int liczbaRat = warunki.Raty;
|
|
|
|
using (var t = session.Logout(editMode: true)) // dokument w buforze
|
|
{
|
|
if (!warunki.IsReadOnlyTerminDni())
|
|
warunki.TerminDni = 21; // przelicza Termin na pierwszej płatności
|
|
if (!warunki.IsReadOnlySposób())
|
|
warunki.Sposób = session.GetKasa().SposobyZaplaty.WgNazwy["Przelew"];
|
|
t.Commit();
|
|
}
|
|
session.Save();
|
|
```
|
|
|
|
**Pułapki:**
|
|
- `WarunkiPłatnościWorker` działa na **pierwszej** płatności i tylko gdy `Raty <= 1` (jedna płatność);
|
|
przy wielu płatnościach (`Raty > 1`) pola są read-only (`IsReadOnly...` zwracają `true`) — wtedy edytuj
|
|
poszczególne płatności bezpośrednio (HANDEL-W77) albo użyj podziału (HANDEL-W76).
|
|
- `TerminDni` to dni od **daty odniesienia** (`TerminLiczonyOd`/data dokumentu), nie data bezwzględna —
|
|
ustawienie `TerminDni` przelicza `Termin`.
|
|
- Edycja terminu może być zablokowana polityką (`IEdycjaTerminuPlatnosci`) — zawsze sprawdzaj
|
|
`IsReadOnlyTermin()`/`IsReadOnlyTerminDni()` przed zapisem.
|
|
- Zmiana `Sposób` przelicza ewidencję ŚP (subewidencję) — nie ustawiaj `EwidencjaSP` „obok", licz na
|
|
spójność workera.
|
|
|
|
---
|
|
|
|
### HANDEL-W79 — Zmiana płatnika (inny niż kontrahent)
|
|
|
|
**Cel:** ustawić na płatności podmiot inny niż kontrahent dokumentu (np. płatnik trzeci) i wykryć tę
|
|
sytuację z poziomu dokumentu.
|
|
|
|
**Warianty:**
|
|
|
|
| Wariant | Mechanizm |
|
|
|---|---|
|
|
| Zmiana płatnika płatności | `p.Podmiot = innyPodmiot` (`IPodmiotKasowy`) |
|
|
| Wykrycie „innego płatnika" | `dok.InnyPłatnik: bool` (read-only — `true`, gdy jakaś płatność ma `Podmiot != Kontrahent`) |
|
|
| Płatnik domyślny kontrahenta | `Kontrahent.Platnik: IPodmiotKasowy` (kalkulowane — nadrzędny z relacji) |
|
|
|
|
**Pola i typy:** `Platnosc.Podmiot: Soneta.Kasa.IPodmiotKasowy` (zapisywalne),
|
|
`DokumentHandlowy.InnyPłatnik: bool` (**kalkulowane, read-only**),
|
|
`IsReadOnlyPodmiot()`. `Kontrahent` implementuje `IPodmiotKasowy`.
|
|
|
|
**Snippet:**
|
|
|
|
```csharp
|
|
// "Inny płatnik" ustawiamy na poziomie POJEDYNCZEJ płatności — pole Podmiot:
|
|
IPodmiotKasowy platnik = session.GetCRM().Kontrahenci.WgKodu["PLATNIK"];
|
|
|
|
using (var t = session.Logout(editMode: true)) // dokument w buforze
|
|
{
|
|
foreach (Platnosc p in dok.Platnosci)
|
|
if (!p.IsReadOnlyPodmiot())
|
|
p.Podmiot = platnik; // rozrachunek przejdzie na nowy podmiot
|
|
t.Commit();
|
|
}
|
|
session.Save();
|
|
|
|
// Odczyt: czy dokument ma płatnika innego niż kontrahent:
|
|
bool inny = dok.InnyPłatnik; // kalkulowane, tylko do odczytu
|
|
```
|
|
|
|
**Pułapki:**
|
|
- `dok.InnyPłatnik` jest **wyłącznie do odczytu** — to flaga wyliczana z porównania `p.Podmiot` z
|
|
`dok.Kontrahent`. Aby „zmienić płatnika", ustaw `Platnosc.Podmiot`, nie próbuj przypisać `InnyPłatnik`.
|
|
- `Podmiot` jest read-only, gdy płatność jest częściowo rozliczona (`KwotaRozliczona != 0`) — sprawdzaj
|
|
`IsReadOnlyPodmiot()`.
|
|
- Zmiana podmiotu przenosi rozrachunek na nowy podmiot i może podmienić zablokowany podmiot na jego
|
|
zamiennik (wbudowana logika) — odczytaj `p.Podmiot` po zmianie, nie zakładaj wartości wejściowej.
|
|
- `Rachunek` musi należeć do nowego `Podmiot` (twardy weryfikator) — po zmianie płatnika zweryfikuj/wyczyść
|
|
rachunek.
|
|
|
|
---
|
|
|
|
### HANDEL-W80 — Odczyt stanu rozliczenia płatności
|
|
|
|
**Cel:** ustalić, czy płatność jest rozliczona w całości, częściowo czy nierozliczona, oraz dotrzeć do
|
|
powiązanych rozliczeń (zapłat).
|
|
|
|
**Warianty:**
|
|
|
|
| Wariant | Pole / kolekcja |
|
|
|---|---|
|
|
| Stan zbiorczy | `p.StanRozliczenia` (`Nierozliczony`/`Czesciowo`/`Calkowicie`/`NiePodlega`) |
|
|
| Rozliczono całkowicie? | `p.Rozliczono: bool`, `p.Zrealizowane: bool` |
|
|
| Kwoty | `p.KwotaRozliczona`, `p.DoRozliczenia` |
|
|
| Data rozliczenia | `p.DataRozliczenia: Date` (`Date.MaxValue` = nierozliczona) |
|
|
| Rozliczono na dzień | `p.RozliczonoDoDnia(Date data)` |
|
|
| Powiązane rozliczenia/transakcje | `p.Dokumenty`, `p.Zaplaty` (kolekcje `RozliczenieSP`) |
|
|
| Czy podlega rozliczeniu | `p.Rozliczana: bool` |
|
|
|
|
**Pola i typy:** `StanRozliczenia: Soneta.Kasa.StanRozliczenia`, `Rozliczono: bool`, `Zrealizowane: bool`,
|
|
`KwotaRozliczona/DoRozliczenia: Currency`, `DataRozliczenia: Date`, `Rozliczana: bool`,
|
|
`Dokumenty`/`Zaplaty` (rozliczenia typu `Soneta.Kasa.RozliczenieSP`),
|
|
metoda `RozliczonoDoDnia(Date, bool wgDatyKsi = false): Currency`.
|
|
|
|
**Snippet:**
|
|
|
|
```csharp
|
|
foreach (Platnosc p in dok.Platnosci)
|
|
{
|
|
switch (p.StanRozliczenia)
|
|
{
|
|
case StanRozliczenia.Calkowicie: /* zapłacona w całości */ break;
|
|
case StanRozliczenia.Czesciowo: /* część zapłacona: p.DoRozliczenia > 0 */ break;
|
|
case StanRozliczenia.Nierozliczony: /* brak zapłat */ break;
|
|
case StanRozliczenia.NiePodlega: /* płatność nierozliczana */ break;
|
|
}
|
|
|
|
Currency zaplaconoDoDzis = p.RozliczonoDoDnia(Date.Today);
|
|
|
|
// Powiązane rozliczenia (transakcje zapłaty):
|
|
foreach (RozliczenieSP r in p.Zaplaty) { /* r.Data, r.KwotaDokumentu, ... */ }
|
|
foreach (RozliczenieSP r in p.Dokumenty) { /* r.Data, r.KwotaZaplaty, ... */ }
|
|
}
|
|
```
|
|
|
|
**Pułapki:**
|
|
- `StanRozliczenia` jest kalkulowane z `KwotaRozliczona`/`Kwota` — nie ustawiaj go; rozliczenia powstają
|
|
przez operacje kasowe/rozliczeniowe, nie przez bezpośredni zapis na płatności.
|
|
- `DataRozliczenia == Date.MaxValue` oznacza „nierozliczona" — nie traktuj `MaxValue` jako realnej daty.
|
|
- Rozliczenia są rozdzielone na dwie kolekcje (`Dokumenty` i `Zaplaty`) zależnie od strony powiązania —
|
|
do pełnego obrazu przejrzyj obie.
|
|
- Dla płatności `Rozliczana == false` (`NiePodlega`) `DoRozliczenia` wynosi zero — nie analizuj jej jak
|
|
zaległości.
|
|
|
|
---
|
|
|
|
### HANDEL-W81 — Płatności w walucie obcej (kwota w walucie vs PLN, kurs)
|
|
|
|
**Cel:** poprawnie odczytać/ustawić płatność walutową — kwotę w walucie obcej, jej przeliczenie na PLN
|
|
oraz kurs i tabelę kursową.
|
|
|
|
**Warianty:**
|
|
|
|
| Wariant | Pole |
|
|
|---|---|
|
|
| Kwota w walucie dokumentu | `p.Kwota: Currency` (symbol = waluta, np. „EUR") |
|
|
| Kwota w PLN (księgowa) | `p.KwotaKsiegi: Currency` |
|
|
| Kurs i tabela | `p.Kurs: double`, `p.TabelaKursowa: TabelaKursowa` |
|
|
| Interfejs walutowy | `IRowWithKurs`: `KwotaWaluty` (= `Kwota`), `KwotaPLN` (= `KwotaKsiegi`) |
|
|
| Słownie | `p.Słownie: string` |
|
|
|
|
**Pola i typy:** `Kwota: Currency` (waluta dokumentu), `KwotaKsiegi: Currency` (PLN),
|
|
`Kurs: double`, `TabelaKursowa: Soneta.Waluty.TabelaKursowa`. `Platnosc` implementuje
|
|
`Soneta.Waluty.IRowWithKurs` (`KwotaWaluty`, `KwotaPLN`).
|
|
|
|
**Snippet:**
|
|
|
|
```csharp
|
|
foreach (Platnosc p in dok.Platnosci)
|
|
{
|
|
if (p.Kwota.Symbol != Currency.SystemSymbol) // płatność walutowa (np. "EUR")
|
|
{
|
|
Currency wWalucie = p.Kwota; // np. 1000 EUR
|
|
Currency wPln = p.KwotaKsiegi; // przeliczenie na PLN
|
|
double kurs = p.Kurs; // kurs zastosowany
|
|
TabelaKursowa tab = p.TabelaKursowa; // tabela kursów (lub null)
|
|
}
|
|
}
|
|
|
|
// Ustawienie kursu ręcznie (gdy dokument/ewidencja walutowa, w buforze):
|
|
using (var t = session.Logout(editMode: true))
|
|
{
|
|
foreach (Platnosc p in dok.Platnosci)
|
|
if (p.Kwota.Symbol != Currency.SystemSymbol && !p.IsReadOnlyTabelaKursowa())
|
|
p.TabelaKursowa = session.GetKasa().EwidencjeSP /* ... */ ?.TabelaKursowa;
|
|
t.Commit();
|
|
}
|
|
session.Save();
|
|
```
|
|
|
|
**Pułapki:**
|
|
- Dla płatności w PLN `Kurs == 1.0` i `TabelaKursowa == null` — przeliczeniem zajmuj się tylko, gdy
|
|
`Kwota.Symbol != Currency.SystemSymbol`.
|
|
- `KwotaKsiegi` wylicza się z `Kwota * Kurs`; jeśli ustawisz tabelę bez kursu na datę dokumentu, kurs może
|
|
pozostać `0.0` (brak kursu) — wtedy `KwotaKsiegi` będzie zerowa. Upewnij się, że tabela kursowa ma kurs
|
|
na `DataDokumentu` (w bazie Demo brak kursów „na dziś" → operacja walutowa rzuca
|
|
`KursWalutyNotFoundException`, por. rozdz. o walutach).
|
|
- Kwota płatności walutowej musi mieć symbol zgodny z walutą dokumentu/ewidencji ŚP — weryfikator ostrzega
|
|
o niezgodności symboli.
|
|
- Sumę płatności w PLN czytaj z `KwotaKsiegi` (lub `IRowWithKurs.KwotaPLN`), nie przeliczaj `Kwota` własnym
|
|
kursem.
|
|
|
|
---
|
|
|
|
### HANDEL-W82 — Powiązanie płatności z terminem i rabatem za wcześniejszą zapłatę
|
|
|
|
**Cel:** obsłużyć rabat za wcześniejszą zapłatę (skonto) — wskazać termin uprawniający do rabatu i odczytać
|
|
jego wpływ na warunki płatności dokumentu.
|
|
|
|
**Warianty:**
|
|
|
|
| Wariant | Mechanizm |
|
|
|---|---|
|
|
| Ustawienie terminu rabatu na dokumencie | `dok.RabatZaTerminPlatnosci.Termin = data` |
|
|
| Odczyt naliczonego rabatu | `dok.RabatZaTerminPlatnosci.Rabat: Percent` |
|
|
| Rodzaj rabatu | `dok.RabatZaTerminPlatnosci.Rodzaj: RodzajRabatuZaTerminPlatnosci` |
|
|
| Termin samej płatności | `p.Termin`, `p.TerminDni` (HANDEL-W77/HANDEL-W78) |
|
|
| Parametry rabatu na kontrahencie | `Kontrahent.RodzajRabatuZaTerminPlatnosci`, `TrybRabatu...`, `IloscDniDlaRabatu`, `WartoscRabatuZaKazdyDzien` |
|
|
|
|
**Pola i typy:** `DokumentHandlowy.RabatZaTerminPlatnosci: Soneta.Handel.RabatZaTerminPlatnosci`
|
|
(subrow) z polami `Termin: Date` (zapisywalne — termin uprawniający do rabatu), `Rabat: Percent`
|
|
(wyliczane), `Rodzaj: RodzajRabatuZaTerminPlatnosci`. Na płatności: `Termin: Date`,
|
|
`TerminDni: int`, `TerminLiczonyOd: Date` (data odniesienia, read-only).
|
|
|
|
**Snippet:**
|
|
|
|
```csharp
|
|
using (var t = session.Logout(editMode: true)) // dokument w buforze, z kontrahentem
|
|
{
|
|
// Termin uprawniający do rabatu za wcześniejszą zapłatę (skonto):
|
|
if (!dok.RabatZaTerminPlatnosci.IsReadOnlyTermin())
|
|
dok.RabatZaTerminPlatnosci.Termin = dok.DataDokumentu.AddDays(7);
|
|
t.Commit();
|
|
}
|
|
session.Save();
|
|
|
|
// Odczyt naliczonego rabatu (zależny od parametrów rabatu kontrahenta):
|
|
Percent rabat = dok.RabatZaTerminPlatnosci.Rabat;
|
|
Date terminRabatu = dok.RabatZaTerminPlatnosci.Termin;
|
|
```
|
|
|
|
**Pułapki:**
|
|
- `RabatZaTerminPlatnosci.Rabat` jest **wyliczany** z parametrów kontrahenta (tryb: progresywny /
|
|
podstawowy / progowy) i różnicy dni między `Termin` rabatu a terminem płatności — nie ustawiaj go wprost.
|
|
- Ustawienie `Termin` < `Date.Today` zeruje rabat i czyści termin — przekazuj datę przyszłą.
|
|
- Termin rabatu można ustawić tylko, gdy **wszystkie** płatności dokumentu mają ten sam termin
|
|
(`Dokument.Platnosci` zgrupowane po `Termin` → jedna grupa); w przeciwnym razie rzuca `RowException`.
|
|
- Edycja może być zablokowana polityką `IEdycjaTerminuPlatnosci` — sprawdzaj `IsReadOnlyTermin()`.
|
|
- Naliczenie rabatu wymaga skonfigurowanych parametrów na kontrahencie
|
|
(`RodzajRabatuZaTerminPlatnosci`, `Tryb...`, progi/wartości) — bez nich `Rabat` pozostanie `Percent.Zero`.
|
|
|
|
---
|
|
|