Latte – výpočet počtu dní před stanovený datum
- Alsatian
- Člen | 175
Ahoj.
V databázi mám uloženo „datum_vystaveni“ (date) jako datum vystavení
faktury.
Další „splatnost_dny“ (int) znamená počet dní splatnosti faktury.
Datum splatnosti si z těchto údajů v LATTE zjistím takto:
{var $datumSplatnost = new \DateTime($zaznam->datum_vystaveni)}
{$datumSplatnost->modify('+'.$zaznam->splatnost_dny.' days')|date:'j. n. Y'}
Jak nyní v LATTE vypsat počet dní, které je faktura po splatnosti? Něco jako nynější datum – $datumSplatnost. Nedaří se mi to :) Děkuji.
- GEpic
- Člen | 566
Proč si neukládáš DATUM vystavení a DATUM splatnosti? Pracuje se s tím všeobecně líp už i na úrovni databáze (různé filtrování, vyhledávání, atp.).
Počet dní po splatnosti zjistíš pak takto
(if $dnuPoSplatnosti > 0
)
/** @var DateTime $datumSplatnosti **/
$dnuPoSplatnosti = (new DateTime())->diff($datumSplatnosti)->format("%a");
Navíc se ti budou hledat lépe celkově faktury po splatnosti – stačí v databázi najít všechny záznamy, jejichž datum po splatnosti je starší než dnešní datum.
Editoval GEpic (4. 10. 2018 22:18)
- Alsatian
- Člen | 175
@GEpic – dost možná na to jdu špatně, to je pravda. Každopádně počet dní po splatnosti ukládám jako číslo proto, že jej takto zadávám do formuláře. Když tedy upravuji fakturu, číslo počet dní můžu jednoduše změnit. Zde by předpokládám zase vznikl problém, jak jej upravovat.
Fci DateTime diff jsem neznal, díky moc. Jdu to nějak zpytlíkovat :) Faktury po splatnosti „zatím“ vyjet nepotřebuji, filtruji pouze neuhrazené. Ale třeba mě to nemine.
Děkuji :)
- Alsatian
- Člen | 175
Kdyby se to někomu hodilo, tady je výsledek.
Definice vlastního filtru v BasePresenter – beforeRender()
$this->template->addFilter('fakturaDnyPoSplatnosti', function($datum, $prictiDny) {
$datumSplatnost = new DateTime($datum);
$datumSplatnost = $datumSplatnost->modify('+' . $prictiDny . ' days');
$datumRozdilSekundy = strtotime(date('Y-m-d 00:00:00', time() ) ) - $datumSplatnost->getTimestamp();
$return = round($datumRozdilSekundy / (24 * 60 * 60), 0);
return $return < 0 ? '0' : $return;
});
Zobrazení v šabloně v případě, že je FA po splatnosti.
{var $test = ($zaznam->datum_vystaveni|fakturaDnyPoSplatnosti:$zaznam->splatnost_dny)}
{if $test}
<badge class="badge badge-outline-danger">{$test}</badge>
{/if}
- David Matějka
- Moderator | 6445
@Alsatian proc ses nakonec rozhodl pracovat s timestampem namisto
DateTime::diff
? ty datetime metody dokazou lepe pracovat se
zaludnostmi jako jsou zmeny casu (letni/normalni)
- Alsatian
- Člen | 175
@GEpic máš samozřejmě pravdu. Vrátil jsem se tedy k tomu a vyřešil zatím následovně.
$datumDnes = new DateTime();
$datumSplatnosti = (new DateTime($datum))->modify('+'.$prictiDny.' days');
$rozdilDny = $datumDnes->diff($datumSplatnosti)->format("%a");
return $datumSplatnosti < $datumDnes && $rozdilDny > 0 ? $rozdilDny : 0;
Poslední řádek vypadá složitě, ale diff nevrací zápornou hodnotu
pokud odečítám budoucí datum od dnešního.
Dá se to udělat i jinak? Aby diff vrátil zápornou hodnotu?
- MajklNajt
- Člen | 502
@Alsatian mohol by si to zefektívniť takto nejako:
$datumDnes = new DateTime();
$datumSplatnosti = $datumVystavenia->modifyClone('+'.$prictiDny.' days');
return $datumSplatnosti < $datumDnes ? $datumDnes->diff($datumSplatnosti)->format("%a"): 0;
Predpokladám, že dátumy sú inštanciou Nette\Utils\DateTime
- GEpic
- Člen | 566
Dá se to udělat i jinak? Aby diff vrátil zápornou hodnotu?
Zkus to takto:
->format("%r%a"); // %r - Sign "-" when negative, empty when positive
nezapomeň si to přetypovat na integer.
EDIT:
@MajklNajt nebo takto:
$datumDnes = new DateTime();
$datumSplatnosti = $datumVystavenia->modifyClone('+'.$prictiDny.' days');
return max(0, (int) $datumDnes->diff($datumSplatnosti)->format("%r%a"));
Jen ještě jedno upozornění – U objektů typu DateTime
,
pokud nepracuješ s časem, je dobré ho ručně přenastavit tak, aby
u každého objektu byl stejný – mohlo by se totiž stát, že ti výsledek
nebude sedět. Popř. toto ošetřovat už při ukládání do databáze
(ideálně).
Každopádně poté je nutné, pokud tvoříš objekt DateTime ručně
(new DateTime()
), čas přenastavit, např. takto:
$datumDnes = (new DateTime())->setTime(0, 0);
// nebo
$datumDnes = new DateTime();
$datumDnes->setTime(0, 0);
Jde totiž o to, že pokud tvoříš objekt z datumu „7.10.2018 13:00“ a chceš zjistit počet dní do „8.10.2018 12:00“, dostaneš zpět 0 dní, ale ty ve svém případě očekáváš 1 den.
Editoval GEpic (7. 10. 2018 12:49)