ugrás a tartalomhoz

MySQL bonyolódás

Termes · 2017. Aug. 3. (Cs), 13.17
Sziasztok!

Kicsit belebonyolódtam. Egy jutalékszámító részleten dolgozom, ami fejtörést okozott.

Adott 3 csomag (id->7,8,9), amit választani lehet a tagságnál. Az ügynök, aki eladja jutalékot kap az üzletből, amit ennek a kódrészletnek kellene kiszámítania. Az első csomag utáni összeget 3 hónapra elosztva kell kifizetni, a többi csomag után járó jutalékot egy összegben. Ezt kell ellenőrizni, hogy jár-e egyáltalán jutalék és, ha igen, akkor mennyi.

Köszi előre is a segítségeket.
  1. <?php  
  2. //...  
  3. $result_bonusz = mysql_query(  
  4.     'SELECT  
  5.         *  
  6.     FROM  
  7.         mt_merchant  
  8.     WHERE  
  9.         year(date_created) = ' . $ev . '  
  10.     AND  
  11.         month(date_created) = ' . $ho . '  
  12.     AND  
  13.         status="active"  
  14.     AND  
  15.         ugynok = ' . $i . '');  
  16. $bonusz_row = mysql_fetch_array($result_bonusz);  
  17.   
  18. if ($bonusz_row['package_id'] == 8) {  
  19.     $bonusz_1 = 30000;  
  20.     $kifizetheto = 1;  
  21. elseif ($bonusz_row['package_id'] == 9) {  
  22.     $bonusz_2 = 50000;  
  23.     $kifizetheto = 1;  
  24. elseif ($bonusz_row['package_id'] == 7) {  
  25.   
  26.     $result_bonusz_ell_3 = mysql_query(  
  27.         'SELECT  
  28.             merchant_id  
  29.         FROM  
  30.             mt_merchant  
  31.         WHERE  
  32.             package_id = 7  
  33.             AND (  
  34.                 date_created BETWEEN (  
  35.                     NOW(), INTERVAL 3 MONTH  
  36.                 ) AND (  
  37.                     NOW(), INTERVAL 2 MONTH  
  38.                 )  
  39.             ) AND  
  40.                 status="active"  
  41.             AND  
  42.                 ugynok = ' . $i . '');  
  43.     if (mysql_num_rows($result_bonusz_ell_3) != 1) {  
  44.         $bonusz_3 = 0;  
  45.     } elseif (mysql_num_rows($result_bonusz_ell_3) == 1) {  
  46.         $bonusz_3 = 10000;  
  47.     } else {  
  48.         $bonusz_3 = 0;  
  49.     }  
  50.   
  51.     $result_bonusz_ell_4 = mysql_query(  
  52.         'SELECT  
  53.             merchant_id  
  54.         FROM  
  55.             mt_merchant  
  56.         WHERE  
  57.             package_id = 7  
  58.             AND (  
  59.                 date_created BETWEEN (  
  60.                     NOW(), INTERVAL 2 MONTH  
  61.                 ) AND (  
  62.                     NOW(), INTERVAL 1 MONTH  
  63.                 )  
  64.             ) AND  
  65.                 status="active"  
  66.             AND  
  67.                 ugynok = ' . $i . '');  
  68.     if (mysql_num_rows($result_bonusz_ell_4) != 1) {  
  69.         $bonusz_4 = 0;  
  70.     } elseif (mysql_num_rows($result_bonusz_ell_4) == 1) {  
  71.         $bonusz_4 = 10000;  
  72.     } else {  
  73.         $bonusz_4 = 0;  
  74.     }  
  75.   
  76.     $bonusz_3 = 10000;  
  77.     $kifizetheto = 3;  
  78.   
  79. else {  
  80.     $bonusz_3 = 0;  
  81.     $kifizetheto = 0;  
  82. }  
  83.   
  84. $bonusz = $bonusz_1 + $bonusz_2 + $bonusz_3 + $bonusz_4;  
  85.   
  86. print $i . " | " . $jutalek . " + " . $bonusz . " <br>";  
  87. //...  
 
1

Problemak

janoszen · 2017. Aug. 3. (Cs), 13.34
Eloszor is, nemi problemak vannak a koddal:

1. Legkozelebb legyszives formazd meg a kodot hogy ne a kepernyo jobb szelen kezdodjon es ne legyen 300+ karakter hosszu egy sor. Ezt most megtettem helyetted.
2. A mysql fuggvenyek deprecated-ek es PHP 7-ben mar nem mukodnek. Helyette allj at a mysqli-re vagy PDO-ra.
3. A kodot SQL injection gyanus, melegen ajanlom a prepared statementekkel valo megismerkedest. (Ha nem tudod mi ez, gondolj a BKK-s bruhahara.)

Ezen felul a problemad megoldasara ha javasolhatom a tesztek irasat. Olvasd ki a szukseges adatokat MySQL-bol es az uzleti logikadat PHP-ban ird meg, ne SQL-ben. Ha ugyesen levalasztod az adatbetoltest, akkor a tesztjeid akar adatbazis nelkul is tudnak mukodni.

Ami a konkret problemadat illeti, sajnos nem nagyon tudunk segiteni mert nem irtad le a szabalyokat hogy ki mikor mennyi bonuszt kap. Sztem ird le magyar mondatokban kod nelkul, listaba szedve hogy kinek mikor jar a jutalek, es akkor jobban tudunk segiteni.

Bonusz pontok:

- A kodod lehetoleg olyan legyen, hogy azt angolul tudo ember programozasi tudas nelkul el tudja olvasni. Ugy kisebb a valoszinusege a hibanak.
- Javaslom, hogy szervezd at a kododat ugy, hogy a csomagokhoz tartozo jutalek ne a kodba legyen beegetve, hanem szinten az adatbazisban keruljon eltarolasra, mert az uzleti vezetoseg tuti fog olyan otlettel jonni, hogy jo lenne ha lenne meg csomag.
2

Köszi

Termes · 2017. Aug. 3. (Cs), 13.56
1. Rendben. A kimásolt kódrészlet a formázások miatt tolódott el ennyire, erre nem figyeltem.

2. Még nem 7-es PHP fut a szerveren, pontosan a módosítások miatt.. idővel :)

3. Köszi.

Ezt a szkriptet cron futtatná le minden hó utolsó napján adott időpontban.
Feladata (lenne) az adatbázisban szereplő ügyfeleket lefuttatni és a jutalékokat kiszámolni, majd beszúrni az adatbázisba.

A csomagok után jutalékot kap az ügynök, illetve egy egyszeri bónuszt a friss kötésért ugyanarra a csomagra. Pl: 1. csomag (id->7) egyszeri bónusz (30000 ft -> 3 hónapra lebontva) és a hozzá tartozó jutalék havonta 3000 forint, amíg aktiv a csomag, tehát fizetve van.

A többi csomag esetén egyszeri bónusz van 30000 és 50000, valamint a jutalék 2000 és 1000 ft.

A bontásban akadtam el igazából. Meg kellene nézni, hogy az aktuális hónapban létezik-e olyan ügyfél, akinek van regisztrációja és aktív (id->7) csomagja. Ha van, akkor 10000 forintot jóváír. Ha nincs, akkor ellenőrzi, hogy az elmúlt 1 hónapban volt-e regisztráció és jelenleg aktív-e a csomagja, ha igen, akkor újra 10000 ft-ot ír jóvá. És így az elmúlt 2 hónapra nézve is ugyanígy jár el. Csak akkor jár a bónusz, ha aktív a csomag.

Azt hiszem erre keresek megoldást.
3

Ertem

janoszen · 2017. Aug. 3. (Cs), 14.23
Ertem, tehat valojaban a Te rendszered ugy nez ki, hogy minden csomaghoz ket szam tartozik: hogy mennyi a jutalek es hany honapra van lebontva (ami lehet egy is).

En ezt a feladatot kicsit maskepp oldanam meg. Tegyuk fel, hogy rendelek egy csomagot amihez 30000 Ft jutalek tartozik 3 reszre bontva. Egyreszt ezt az infot DB-ben tarolnam hogy kesobb konnyu legyen uj jutalekokat felvenni. Masreszt amikor megveszem a csomagot, akkor a 3 jutalekreszt azonnal elore beirnam egy "elojegyzes" tablaba. Ide felvinnem azt, hogy 1. kinek 2. mennyi jutalek 3. mikor 4. mely elofizetes aktivitasa eseten jar.

Vagyis a cronjobodnak annyi a feladat a hogy ezt az elojegyzes tablat nezi meg, hogy melyek azok az elojegyzesek amik meg nem lettek feldolgozva es a mai napnal korabban jarnak. Az elofizetes ID alapjan megnezed hogy tenylegesen jar-e, es ha igen, akkor tenylegesen jova is irod, majd torlod az elojegyzest.

Igy egyreszt konnyebb lesz boviteni a rendszert, masreszt egy csomo szivasba nem szaladsz bele.
4

Nem olyan egyszerű ez nekem

Termes · 2017. Aug. 3. (Cs), 14.48
Az igazsághoz tartozik, hogy van egy alaprendszer, amihez természetesen semmi közöm. Ez jól is működik, ám jött az ötlet, hogy kibővíthetném magamnak ezzel a jutalékos rendszerrel. Na, innentől nem működik a dolog :)

Ez egy cégadatbázis, melybe lehet regisztrálni cégeknek, ehhez jönnek az üzletkötők.

Az általam megálmodott szkript a már meglévő adatbázisba nyúlkálva hozná össze a dolgot. Mivel az alaprendszer yii keretrendszert használ, így megoldott, hogy nem nyúlok bele. :)

Úgy kellene megoldanom, hogy nem bántom a rendszert.

Emiatt kuszálódtam össze. Tehát a regisztráció menetébe nem tudok belenyúlni, csak a kész adatbázissal dolgozhatok.

Az egyszeri kifizetéseket le tudom kezelni, megnézem, hogy abban a hónapban van-e új regisztrált, aki fizetett a csomagért, ha van akkor jár.

Itt a 3 havi lebontást nem értem, hogyan tudnám megoldani. Hogyan követhetném nyomon? Csak akkor jár a bónusz, ha aktív a csomag és maximum 3 egymást követő hónapig jár. Tehát, ha csak az első hónapban fizet és tovább nem, akkor csak 10000 forint jár, ha kettőt fizet, akkor 20000 és ha hármat, akkor a 30000. Vagyis 10-10-10E.

Úgy oldottam meg eddig, hogy megszámoljuk, hogy hány üzletkötő van és egy hurokban szépen egymás után lefuttatjuk a lekérdezéseket. Nyilván van jobb megoldás is, de az én szintemen kellene megoldani amennyire csak lehetséges. :)
5

Nem

janoszen · 2017. Aug. 4. (P), 09.26
Figy, ilyen jutalékokat hardkódolni a legrosszabb ötlet. Az üzleti vezetés állandóan új kérésekkel (most legyen 4 hónap, stb) fog jönni és a végén egy hatalmas spagetti lesz a kód.

Nézzük részletesen. Amikor megtörténik a vásárlás, kiolvasod a csomag adatait:
  1. SELECT  
  2.   csomag_id,  
  3.   havi_jutalek,  
  4.   jutalek_honapok  
  5. FROM  
  6.   csomagok  
  7. WHERE  
  8.   ...  
Ezek után beszúrod az előjegyzést egy for loopban:
  1. for ($i=0;$i<$jutalek_honapok;$i++) {  
  2.   sql("  
  3.     INSERT INTO jutalek_elojegyzes (  
  4.       ugynok_id,  
  5.       elofizetes_id,  
  6.       targynap  
  7.       jutalek  
  8.     VALUES (  
  9.       ?,  
  10.       ?,  
  11.       DATE_ADD(NOW(), INTERVAL ? MONTH),  
  12.       ?  
  13.     ",  
  14.     $ugynok_id,  
  15.     $elofizetes_id,  
  16.     $i,  
  17.     $havi_jutalek  
  18.   );  
  19. }  
Az sql() függvény itt egy általam elképzelt valami ami a kérdőjelek helyére biztonságos módon behelyettesíti a paramétereket pl PDO-val.

Ha megnézed, ez a fenti kód egy hónap elosztással beszúrja az előjegyzés táblába a sorokat.

Na most, a cronjobodnak utána csak annyi dolga van hogy ezen végig menjen:
  1. $rows = sql("  
  2. SELECT  
  3.   elojegyzes_id,  
  4.   ugynok_id,  
  5.   elofizetes_id,  
  6.   jutalek  
  7. FROM  
  8.   jutalek_elojegyzes  
  9. WHERE  
  10.   targynap<NOW()  
  11. ");  
  12. foreach ($rows as $row) {  
  13.   if (elofizetes_aktiv($row[" elofizetes_id"], $row["targynap"])) {  
  14.      jutalek_jovair($row["ugynok_id"], $row["jutalek"]);  
  15.   }  
  16.   sql("DELETE FROM jutalek_elojegyzes WHERE elojegyzes_id=?"$row["elojegyzes_id"]);  
  17. }  
És ennyi. Mennyivel egyszerűbb, nem? (Annyira egyszerű, hogy mobilon be tudtam pötyögni.) Érdemes strukturálni a kódodat, úgy sokkal kevésbé gabalyodsz bele.

Még egy megjegyzés: ha valamiért nem akarsz hozzányúlni a vásárlási folyamathoz, az sem probléma, azt is elvégezheted cronjobból, csak jegyezd fel melyik vásárlást dolgoztad már fel.
6

Wow

Termes · 2017. Aug. 4. (P), 10.07
Köszönöm a segítséget és a kritikát. Neki is ugrok.
7

Tranzakcio

janoszen · 2017. Aug. 4. (P), 11.01
Arra meg esetleg erdemes figyelni, hogy a cronjobos feldolgozast erdemes egy tranzakciobol csinalni. Ha lerohad, akkor ne legyen felig kiirt adat. :)