#!/usr/bin/perl
# Podívá se do databáze plateb došlých na účet Deskohraní, zda přišly nějaké platby s variabilním symbolem přihlášených hráčů.
# Pokud ano, napíše do databáze mso, že je zaplaceno. V případě nesrovnalostí (jiná částka) pošle mail Kláře.
# Předpokládané použití: pouštět pravidelně cronem.
# Nejde tedy o skript CGI, i když je kvůli pohodlí uložen vedle skriptů CGI a nic špatného se nestane, když bude puštěn jako CGI.
# Copyright © 2011, 2013 Dan Zeman <zeman@ufal.mff.cuni.cz>
# Licence: GNU GPL
# 25.9.2013: doplněno nové číslo účtu

use utf8;
use open ':utf8';
binmode(STDIN, ':utf8');
binmode(STDOUT, ':utf8');
binmode(STDERR, ':utf8');
use lib '/s/w/lib/dan';
use lib '/s/w/lib/cgi/mso/vnitro';
use dzsql;
use mail;
use cas;
use mso;

###!!! Tohle není zrovna bezpečné, ale má-li se úloha pouštět automaticky cronem, lepší řešení momentálně neznám.
$ENV{USER} = 'web_deskohrani';
$ENV{DBI_ROOT_PASS} = 'mLSsZYHEKRyTfbnq';
# Připojit se k databázi Deskohraní.
$databaze_mso = mso::pripojit_se_k_databazi();
# Připojit se k databázi pohybů na účtu.
$databaze_banka = pripojit_se_k_databazi_pohybu_na_uctu();
# Získat z databáze Deskohraní seznam očekávaných plateb.
$ocekavane_platby = mso::dotazat_se_databaze($databaze_mso, 'vs', 'datum_prihlasky', '_celkem_startovne', 'osoby_auto ORDER BY vs');
sleep(10);
# Vždy se lze přihlásit pouze na jeden ročník: ten nejbližší, který bude, případně
# ten, který právě probíhá. Zjistit, který ročník to je, a přepsat parametr rok,
# ať už tam měl uživatel cokoli.
$ted = cas::ted();
$roky = mso::dotazat_se_databaze($databaze_mso, 'rok', 'konec', 'vcasne_prihlasky_do', 'rocniky ORDER BY rok');
for(my $i = 0; $i<=$#{$roky}; $i++)
{
    $rok = $roky->[$i]{rok};
    $vcasne_prihlasky_do = $roky->[$i]{vcasne_prihlasky_do};
    if($ted->{eden} <= cas::datum2eden($roky->[$i]{konec}))
    {
        last;
    }
}
# Pro kontrolu vypsat očekávané platby.
foreach my $op (@{$ocekavane_platby})
{
    my $po_sleve = 0.8*$op->{_celkem_startovne};
    print("Očekáváme VS $op->{vs}: $op->{_celkem_startovne} Kč (po slevě $po_sleve Kč)\n");
}
# Získat z databáze pohybů na účtu seznam příchozích plateb.
$dosle_platby = mso::dotazat_se_databaze($databaze_banka, 'datum', 'vs', 'castka', "banka WHERE (nas_ucet='116674103/0300' OR nas_ucet='2300363697/2010') AND castka>0 ORDER BY datum");
# Pro kontrolu vypsat došlé platby.
$aktualni_rok = $ted->{rok};
my $n = scalar(grep {$_->{datum} =~ m/^$aktualni_rok-/} @{$dosle_platby});
if($n==0)
{
    print("Nebyly nalezeny žádné došlé platby za rok $aktualni_rok.\n");
}
else
{
    print("Bylo nalezeno $n došlých plateb za rok $aktualni_rok.\n");
}
foreach my $dp (@{$dosle_platby})
{
    if($dp->{datum} =~ m/^$aktualni_rok-/ && $dp->{vs} =~ m/\d/)
    {
        # Startovné se platilo na různé účty u různých bank. Některé nám dávají VS zarovnaný zleva nulami, jiné ne. Sjednotit.
        $dp->{vs} = sprintf('%010d', $dp->{vs});
        # Pokud první dvě číslice VS nemohou být číslem měsíce, není to platba, která by nás mohla zajímat.
        my $mesic = substr($dp->{vs}, 0, 2);
        next unless($mesic>=1 && $mesic<=12);
        printf("$dp->{datum}: %10d: $dp->{castka} Kč\n", $dp->{vs});
    }
}
# Zjistit, jestli mezi došlými platbami je nějaká očekávaná.
foreach my $op (@{$ocekavane_platby})
{
    # U došlých plateb jsou variabilní symboly doplněné zleva nulami na deset číslic, naše hash klíče tedy musí vypadat stejně.
    my $vs = sprintf('%010d', $op->{vs});
    # U plateb předem ve skutečnosti očekáváme startovné snížené o slevu 20 % (která se poskytuje právě za platbu předem).
    my $po_sleve = 0.8*$op->{_celkem_startovne};
    $ocekavane_vs{$vs} = $po_sleve;
    $nezlevnene_vs{$vs} = $op->{_celkem_startovne};
    # Ke každému variabilnímu symbolu si také nahashovat odpovídající datum přihlášky
    # (i když se z vs dá téměř dopočítat), podle kterého najdeme odpovídající záznamy v tabulce prihlasky_auto.
    $datum_prihlasky{$vs} = $op->{datum_prihlasky};
}
foreach my $dp (@{$dosle_platby})
{
    if(exists($ocekavane_vs{$dp->{vs}}))
    {
        # Jestliže se skutečná částka rovná očekávané částce, zapsat do databáze mso, že bylo zaplaceno. A jestli je momentálně nárok na slevu.
        if($dp->{castka}==$ocekavane_vs{$dp->{vs}} and $ted->{eden} <= cas::datum2eden($vcasne_prihlasky_do)+8)
        {
            print("Dne $dp->{datum} přišla platba ve výši $dp->{castka} Kč, kterou jsme očekávali s variabilním symbolem $dp->{vs}.\n");
            # Zapsat do databáze mso, že bylo zaplaceno.
            dzsql::update($databaze_mso, 'osoby_auto', { 'values' => { 'vs' => $dp->{vs}, 'zaplaceno_dne' => $dp->{datum} }, 'wfields' => ['vs'], 'ufields' => ['vs', 'zaplaceno_dne'] })
                or print STDERR ("Nepodařilo se přidat údaj o zaplacení do tabulky osoby_auto: $DBI::errstr\n$dzsql::dotaz\n");
            # Tohle ale nestačí. Každá jednotlivá přihláška na akci má u sebe poznámku o placení, kterou musíme vyplnit,
            # aby se to projevilo na prezenčních listinách.
            # Získat seznam přihlášek s daným variabilním symbolem.
            my @nazvy = ('datum_prihlasky', 'rok', 'kod_hry', 'kod_turnaje', 'ma_dati', 'dal', 'zpusob_placeni');
            my @nfields = ('rok', 'ma_dati', 'dal');
            my $prihlasky = dzsql::select($databaze_mso, 'prihlasky_auto', { 'values' => { 'datum_prihlasky' => $datum_prihlasky{$dp->{vs}} }, 'wfields' => ['datum_prihlasky'], 'sfields' => \@nazvy });
            foreach my $p (@{$prihlasky})
            {
                # Jestliže jsme dostali celkovou očekávanou částku po slevě,
                # předpokládáme, že částky "má dáti" jsou u všech přihlášek vyplněné správně (před slevou)
                # a vypočítáme z nich, kolik tedy bylo (po slevě) zaplaceno na danou akci.
                $p->{dal} = int(0.8*$p->{ma_dati});
                $p->{zpusob_placeni} = "převodem $dp->{datum}";
                dzsql::update($databaze_mso, 'prihlasky_auto', { 'values' => $p, 'wfields' => ['datum_prihlasky', 'rok', 'kod_hry', 'kod_turnaje'], 'ufields' => \@nazvy, 'nfields' => \@nfields })
                    or print STDERR ("Nepodařilo se přidat údaj o zaplacení do tabulky prihlasky_auto: $DBI::errstr\n$dzsql::dotaz\n");
            }
            # Poslat mail Kláře.
            mail::odeslat
            (
                'From'    => 'robot@hrejsi.cz',
                'To'      => 'klara@hrejsi.cz, danzeman11@gmail.com',
                'Subject' => 'Platba VS '.$dp->{vs},
                'text'    => "Dne $dp->{datum} přišla platba za Deskohraní ve výši $dp->{castka} Kč s variabilním symbolem $dp->{vs}.\n".
                             "http://deskohrani.cz/cgi/mso/vnitro/osoby.pl?vs=$dp->{vs}\n"
            );
        }
        # Jestliže se skutečná částka liší od očekávané částky, ale odpovídá očekávané částce před slevou, zapsat taky, že bylo zaplaceno, ale poslat Kláře trochu jiný e-mail.
        elsif($dp->{castka}==$nezlevnene_vs{$dp->{vs}})
        {
            print("Dne $dp->{datum} přišla platba ve výši $dp->{castka} Kč s variabilním symbolem $dp->{vs}. To je bez slevy, se slevou jsme očekávali $ocekavane_vs{$dp->{vs}} Kč.\n");
            # Zapsat do databáze mso, že bylo zaplaceno.
            dzsql::update($databaze_mso, 'osoby_auto', { 'values' => { 'vs' => $dp->{vs}, 'zaplaceno_dne' => $dp->{datum} }, 'wfields' => ['vs'], 'ufields' => ['vs', 'zaplaceno_dne'] })
                or print STDERR ("Nepodařilo se přidat údaj o zaplacení do tabulky osoby_auto: $DBI::errstr\n$dzsql::dotaz\n");
            # Tohle ale nestačí. Každá jednotlivá přihláška na akci má u sebe poznámku o placení, kterou musíme vyplnit,
            # aby se to projevilo na prezenčních listinách.
            # Získat seznam přihlášek s daným variabilním symbolem.
            my @nazvy = ('datum_prihlasky', 'rok', 'kod_hry', 'kod_turnaje', 'ma_dati', 'dal', 'zpusob_placeni');
            my @nfields = ('rok', 'ma_dati', 'dal');
            my $prihlasky = dzsql::select($databaze_mso, 'prihlasky_auto', { 'values' => { 'datum_prihlasky' => $datum_prihlasky{$dp->{vs}} }, 'wfields' => ['datum_prihlasky'], 'sfields' => \@nazvy });
            foreach my $p (@{$prihlasky})
            {
                # Vzhledem k tomu, že plátce si nezapočítal slevu, zaplatil to, co už máme uvedeno jako "má dáti" (před slevou).
                $p->{dal} = $p->{ma_dati};
                $p->{zpusob_placeni} = "převodem $dp->{datum}";
                dzsql::update($databaze_mso, 'prihlasky_auto', { 'values' => $p, 'wfields' => ['datum_prihlasky', 'rok', 'kod_hry', 'kod_turnaje'], 'ufields' => \@nazvy, 'nfields' => \@nfields })
                    or print STDERR ("Nepodařilo se přidat údaj o zaplacení do tabulky prihlasky_auto: $DBI::errstr\n$dzsql::dotaz\n");
            }
            # Poslat mail Kláře.
            mail::odeslat
            (
                'From'    => 'robot@hrejsi.cz',
                'To'      => 'klara@hrejsi.cz, danzeman11@gmail.com',
                'Subject' => 'Platba VS '.$dp->{vs},
                'text'    => "Dne $dp->{datum} přišla platba za Deskohraní ve výši $dp->{castka} Kč s variabilním symbolem $dp->{vs}.\n".
                             "Plátce si nezapočítal slevu, po slevě by to bylo $ocekavane_vs{$dp->{vs}} Kč.\n".
                             "http://deskohrani.cz/cgi/mso/vnitro/osoby.pl?vs=$dp->{vs}\n"
            );
        }
        # Jestliže se skutečná částka liší od očekávané částky, poslat e-mail Kláře, aby se spojila s plátcem a vyjasnila si nesrovnalosti.
        else
        {
            my $pred_slevou = $ocekavane_vs{$dp->{vs}}/0.8;
            my $hlaseni = "Dne $dp->{datum} přišla platba ve výši $dp->{castka} Kč s variabilním symbolem $dp->{vs}, my jsme ale pod tímto symbolem očekávali částku $ocekavane_vs{$dp->{vs}} Kč (po slevě; před slevou to bylo $pred_slevou).\n";
            $hlaseni .= "http://deskohrani.cz/cgi/mso/vnitro/osoby.pl?vs=$dp->{vs}\n";
            print($hlaseni);
            # Poslat mail Kláře.
            mail::odeslat
            (
                'From'    => 'robot@hrejsi.cz',
                'To'      => 'klara@hrejsi.cz, danzeman11@gmail.com',
                'Subject' => 'Necekana castka VS '.$dp->{vs},
                'text'    => $hlaseni
            );
        }
    }
}



#------------------------------------------------------------------------------
# Připojí se k databázi pohybů na účtu.
#------------------------------------------------------------------------------
sub pripojit_se_k_databazi_pohybu_na_uctu
{
    # Připojit se k databázi. Proměnné prostředí momentálně nastavujeme na začátku tohoto skriptu.
    my $dbi_uzivatel = $ENV{USER};
    my $dbi_heslo = $ENV{DBI_ROOT_PASS};
    my $databaze = DBI->connect('DBI:mysql:mailautomat', $dbi_uzivatel, $dbi_heslo)
      or print STDERR ("Nelze se pripojit k databazi: $DBI::errstr\n");
    # Nastavit kódování klienta, spojení a výsledků.
    $databaze->prepare("SET NAMES 'utf8'")->execute();
    return $databaze;
}
