Untested fix to coke code (flushes buffer beofre reading)
[tpg/opendispense2.git] / src / server / dispense.c
1 /**
2  */
3 #include "common.h"
4 #include <stdlib.h>
5 #include <limits.h>
6
7  int    _GetMinBalance(int Account);
8  int    _Transfer(int Source, int Destination, int Ammount, const char *Reason);
9
10 // === CODE ===
11 /**
12  * \brief Dispense an item for a user
13  * 
14  * The core of the dispense system, I kinda like it :)
15  */
16 int DispenseItem(int ActualUser, int User, tItem *Item)
17 {
18          int    ret;
19         tHandler        *handler;
20         char    *username, *actualUsername;
21         char    *reason;
22         
23         handler = Item->Handler;
24         
25         // Check if the dispense is possible
26         if( handler->CanDispense ) {
27                 ret = handler->CanDispense( User, Item->ID );
28                 if(ret) return 1;       // 1: Unable to dispense
29         }
30
31         // Subtract the balance
32         if( Item->Price )
33         {
34                 reason = mkstr("Dispense - %s:%i %s", handler->Name, Item->ID, Item->Name);
35                 if( !reason )   reason = Item->Name;    // TODO: Should I instead return an error?
36                 ret = _Transfer( User, Bank_GetAcctByName(COKEBANK_SALES_ACCT), Item->Price, reason);
37                 free(reason);
38                 if(ret) return 2;       // 2: No balance
39         }
40         
41         // Get username for debugging
42         username = Bank_GetAcctName(User);
43         
44         // Actually do the dispense
45         if( handler->DoDispense ) {
46                 ret = handler->DoDispense( User, Item->ID );
47                 if(ret) {
48                         Log_Error("Dispense failed after deducting cost (%s dispensing %s - %ic)",
49                                 username, Item->Name, Item->Price);
50                         if( Item->Price )
51                                 _Transfer( Bank_GetAcctByName(COKEBANK_SALES_ACCT), User, Item->Price, "rollback" );
52                         free( username );
53                         return -1;      // 1: Unkown Error again
54                 }
55         }
56         
57         actualUsername = Bank_GetAcctName(ActualUser);
58         
59         // And log that it happened
60         Log_Info("dispense '%s' (%s:%i) for %s by %s [cost %i, balance %i]",
61                 Item->Name, handler->Name, Item->ID,
62                 username, actualUsername, Item->Price, Bank_GetBalance(User)
63                 );
64         
65         free( username );
66         free( actualUsername );
67         return 0;       // 0: EOK
68 }
69
70 /**
71  * \brief Give money from one user to another
72  */
73 int DispenseGive(int ActualUser, int SrcUser, int DestUser, int Ammount, const char *ReasonGiven)
74 {
75          int    ret;
76         char    *actualUsername;
77         char    *srcName, *dstName;
78         
79         if( Ammount < 0 )       return 1;       // Um... negative give? Not on my watch!
80         
81         ret = _Transfer( SrcUser, DestUser, Ammount, ReasonGiven );
82         if(ret) return 2;       // No Balance
83         
84         
85         actualUsername = Bank_GetAcctName(ActualUser);
86         srcName = Bank_GetAcctName(SrcUser);
87         dstName = Bank_GetAcctName(DestUser);
88         
89         Log_Info("give %i to %s from %s by %s [balances %i, %i] - %s",
90                 Ammount, dstName, srcName, actualUsername,
91                 Bank_GetBalance(SrcUser), Bank_GetBalance(DestUser),
92                 ReasonGiven
93                 );
94         
95         free(srcName);
96         free(dstName);
97         free(actualUsername);
98         
99         return 0;
100 }
101
102 /**
103  * \brief Add money to an account
104  */
105 int DispenseAdd(int ActualUser, int User, int Ammount, const char *ReasonGiven)
106 {
107          int    ret;
108         char    *dstName, *byName;
109         
110         ret = _Transfer( Bank_GetAcctByName(COKEBANK_DEBT_ACCT), User, Ammount, ReasonGiven );
111         if(ret) return 2;
112         
113         byName = Bank_GetAcctName(ActualUser);
114         dstName = Bank_GetAcctName(User);
115         
116         Log_Info("add %i to %s by %s [balance %i] - %s",
117                 Ammount, dstName, byName, Bank_GetBalance(User), ReasonGiven
118                 );
119         
120         free(byName);
121         free(dstName);
122         
123         return 0;
124 }
125
126 /**
127  * \brief Donate money to the club
128  */
129 int DispenseDonate(int ActualUser, int User, int Ammount, const char *ReasonGiven)
130 {
131          int    ret;
132         char    *srcName, *byName;
133         
134         if( Ammount < 0 )       return 2;
135         
136         ret = _Transfer( User, Bank_GetAcctByName(COKEBANK_DEBT_ACCT), Ammount, ReasonGiven );
137         if(ret) return 2;
138         
139         byName = Bank_GetAcctName(ActualUser);
140         srcName = Bank_GetAcctName(User);
141         
142         Log_Info("donate %i from %s by %s [balance %i] - %s",
143                 Ammount, srcName, byName, Bank_GetBalance(User), ReasonGiven
144                 );
145         
146         free(byName);
147         free(srcName);
148         
149         return 0;
150 }
151
152 // --- Internal Functions ---
153 int _GetMinBalance(int Account)
154 {
155          int    flags = Bank_GetFlags(Account);
156         
157         // - Internal accounts have no lower bound
158         if( flags & USER_FLAG_INTERNAL )        return INT_MIN;
159         
160         // Admin to -$10
161         if( flags & USER_FLAG_ADMIN )   return -1000;
162         
163         // Coke to -$5
164         if( flags & USER_FLAG_COKE )    return -500;
165         
166         // Anyone else, non-negative
167         return 0;
168 }
169
170 int _Transfer(int Source, int Destination, int Ammount, const char *Reason)
171 {
172         if( Ammount > 0 )
173         {
174                 if( Bank_GetBalance(Source) + Ammount < _GetMinBalance(Source) )
175                         return 1;
176         }
177         else
178         {
179                 if( Bank_GetBalance(Destination) - Ammount < _GetMinBalance(Destination) )
180                         return 1;
181         }
182         
183         return Bank_Transfer(Source, Destination, Ammount, Reason);
184 }

UCC git Repository :: git.ucc.asn.au