@@ -2,9 +2,12 @@ package wallet
2
2
3
3
import (
4
4
"context"
5
+ "log"
5
6
"time"
6
7
8
+ "github.com/google/uuid"
7
9
"github.com/thinc-org/10-days-paotooong/gen/ent"
10
+ "github.com/thinc-org/10-days-paotooong/gen/ent/pleasepay"
8
11
v1 "github.com/thinc-org/10-days-paotooong/gen/proto/wallet/v1"
9
12
user_repo "github.com/thinc-org/10-days-paotooong/internal/user"
10
13
"google.golang.org/grpc/codes"
@@ -147,3 +150,206 @@ func (s *walletServiceImpl) Topup(ctx context.Context, request *v1.TopupRequest)
147
150
},
148
151
}, nil
149
152
}
153
+
154
+ func (s * walletServiceImpl ) CreatePleasePay (ctx context.Context , request * v1.CreatePleasePayRequest ) (* v1.CreatePleasePayResponse , error ) {
155
+ user , err := s .userRepo .InferUserFromContext (ctx )
156
+ if err != nil {
157
+ return nil , err
158
+ }
159
+
160
+ pleasePay , err := s .client .PleasePay .Create ().SetReceiverID (user .ID ).SetAmount (float64 (request .GetAmount ())).Save (ctx )
161
+ if err != nil {
162
+ log .Printf ("error: %v" , err )
163
+ return nil , status .Error (codes .Internal , "internal server error" )
164
+ }
165
+
166
+ return & v1.CreatePleasePayResponse {
167
+ PleasePay : & v1.PleasePay {
168
+ Id : pleasePay .ID .String (),
169
+ State : mapPleasePayState (pleasePay .State ),
170
+ ReceiverId : user .ID .String (),
171
+ Amount : float32 (pleasePay .Amount ),
172
+ },
173
+ }, nil
174
+ }
175
+
176
+ func (s * walletServiceImpl ) GetPleasePay (ctx context.Context , request * v1.GetPleasePayRequest ) (* v1.GetPleasePayResponse , error ) {
177
+ userEnt , err := s .userRepo .InferUserFromContext (ctx )
178
+ if err != nil {
179
+ return nil , err
180
+ }
181
+
182
+ ppId , err := uuid .Parse (request .GetId ())
183
+ if err != nil {
184
+ return nil , status .Error (codes .FailedPrecondition , "invalid uuid" )
185
+ }
186
+
187
+ pleasePay , err := s .client .PleasePay .Query ().Where (
188
+ pleasepay .ID (ppId ),
189
+ ).First (ctx )
190
+ if err != nil {
191
+ if ent .IsNotFound (err ) {
192
+ return nil , status .Error (codes .NotFound , "please pay not found" )
193
+ }
194
+ return nil , err
195
+ }
196
+
197
+ receiver , err := pleasePay .QueryReceiver ().First (ctx )
198
+ if receiver .ID != userEnt .ID {
199
+ return nil , status .Error (codes .PermissionDenied , "this is not your please pay" )
200
+ }
201
+
202
+ response := & v1.GetPleasePayResponse {
203
+ PleasePay : & v1.PleasePay {
204
+ Id : pleasePay .ID .String (),
205
+ State : mapPleasePayState (pleasePay .State ),
206
+ ReceiverId : receiver .ID .String (),
207
+ Amount : float32 (pleasePay .Amount ),
208
+ },
209
+ }
210
+
211
+ t , err := pleasePay .QueryTransaction ().First (ctx )
212
+ if err != nil && ! ent .IsNotFound (err ) {
213
+ return nil , err
214
+ }
215
+
216
+ if t != nil {
217
+ payer , err := t .QueryPayer ().First (ctx )
218
+ if err != nil {
219
+ log .Printf ("cannot find user %v in transaction %v" , t .PayerID , t .ID )
220
+ return nil , status .Error (codes .Internal , "internal server error" )
221
+ }
222
+
223
+ receiver , err := t .QueryReceiver ().First (ctx )
224
+ if err != nil {
225
+ log .Printf ("cannot find user %v in transaction %v" , t .ReceiverID , t .ID )
226
+ return nil , status .Error (codes .Internal , "internal server error" )
227
+ }
228
+
229
+ response .PleasePay .Transaction = & v1.Transaction {
230
+ TransactionId : t .ID .String (),
231
+ Payer : & v1.UserTransaction {
232
+ Id : payer .ID .String (),
233
+ FirstName : payer .FirstName ,
234
+ FamilyName : payer .FamilyName ,
235
+ },
236
+ Receiver : & v1.UserTransaction {
237
+ Id : receiver .ID .String (),
238
+ FirstName : receiver .FirstName ,
239
+ FamilyName : receiver .FamilyName ,
240
+ },
241
+ Amount : float32 (t .Amount ),
242
+ CreatedAt : & timestamppb.Timestamp {
243
+ Seconds : t .CreatedAt .Unix (),
244
+ },
245
+ Type : v1 .TransactionType_TRANSACTION_TYPE_PAY ,
246
+ }
247
+ }
248
+
249
+ return response , nil
250
+ }
251
+
252
+ func (s * walletServiceImpl ) PayPleasePay (ctx context.Context , request * v1.PayPleasePayRequest ) (* v1.PayPleasePayResponse , error ) {
253
+ payer , err := s .userRepo .InferUserFromContext (ctx )
254
+ if err != nil {
255
+ return nil , err
256
+ }
257
+
258
+ ppId , err := uuid .Parse (request .GetId ())
259
+ if err != nil {
260
+ return nil , status .Error (codes .FailedPrecondition , "invalid uuid" )
261
+ }
262
+
263
+ pleasePay , err := s .client .PleasePay .Query ().Where (
264
+ pleasepay .ID (ppId ),
265
+ ).First (ctx )
266
+ if err != nil {
267
+ if ent .IsNotFound (err ) {
268
+ return nil , status .Error (codes .NotFound , "please pay not found" )
269
+ }
270
+ return nil , err
271
+ }
272
+
273
+ if float32 (payer .Money ) < float32 (pleasePay .Amount ) {
274
+ return nil , status .Error (codes .FailedPrecondition , "not enough money" )
275
+ }
276
+
277
+ receiver , err := pleasePay .QueryReceiver ().First (ctx )
278
+ if err != nil {
279
+ return nil , status .Error (codes .NotFound , "receiver not found" )
280
+ }
281
+
282
+ amount := pleasePay .Amount
283
+
284
+ tx , err := s .client .Tx (ctx )
285
+ if err != nil {
286
+ return nil , status .Error (codes .Internal , "internal server error" )
287
+ }
288
+
289
+ _ , err = tx .User .UpdateOneID (receiver .ID ).SetMoney (receiver .Money + float64 (amount )).Save (ctx )
290
+ if err != nil {
291
+ tx .Rollback ()
292
+ return nil , status .Error (codes .Internal , "internal server error" )
293
+ }
294
+
295
+ _ , err = tx .User .UpdateOneID (payer .ID ).SetMoney (payer .Money - float64 (amount )).Save (ctx )
296
+ if err != nil {
297
+ tx .Rollback ()
298
+ return nil , status .Error (codes .Internal , "internal server error" )
299
+ }
300
+
301
+ transaction , err := tx .Transaction .Create ().SetPayer (payer ).SetReceiver (receiver ).SetAmount (float64 (amount )).SetType ("pay" ).Save (ctx )
302
+ if err != nil {
303
+ tx .Rollback ()
304
+ return nil , status .Error (codes .Internal , "internal server error" )
305
+ }
306
+
307
+ pleasePayAfter , err := tx .PleasePay .UpdateOneID (pleasePay .ID ).SetState ("PAID" ).Save (ctx )
308
+ if err != nil {
309
+ tx .Rollback ()
310
+ return nil , status .Error (codes .Internal , "internal server error" )
311
+ }
312
+
313
+ err = tx .Commit ()
314
+ if err != nil {
315
+ return nil , status .Error (codes .Internal , "internal server error" )
316
+ }
317
+
318
+ return & v1.PayPleasePayResponse {
319
+ PleasePay : & v1.PleasePay {
320
+ Id : pleasePayAfter .ID .String (),
321
+ State : mapPleasePayState (pleasePayAfter .State ),
322
+ ReceiverId : receiver .ID .String (),
323
+ Amount : float32 (pleasePay .Amount ),
324
+ Transaction : & v1.Transaction {
325
+ TransactionId : transaction .ID .String (),
326
+ Payer : & v1.UserTransaction {
327
+ Id : payer .ID .String (),
328
+ FirstName : payer .FirstName ,
329
+ FamilyName : payer .FamilyName ,
330
+ },
331
+ Receiver : & v1.UserTransaction {
332
+ Id : receiver .ID .String (),
333
+ FirstName : receiver .FirstName ,
334
+ FamilyName : receiver .FamilyName ,
335
+ },
336
+ Amount : float32 (transaction .Amount ),
337
+ CreatedAt : & timestamppb.Timestamp {
338
+ Seconds : transaction .CreatedAt .Unix (),
339
+ },
340
+ Type : v1 .TransactionType_TRANSACTION_TYPE_PAY ,
341
+ },
342
+ },
343
+ }, nil
344
+ }
345
+
346
+ func mapPleasePayState (state string ) v1.PleasePayState {
347
+ switch state {
348
+ case "PENDING" :
349
+ return v1 .PleasePayState_PLEASE_PAY_STATE_PENDING
350
+ case "PAID" :
351
+ return v1 .PleasePayState_PLEASE_PAY_STATE_PAID
352
+ default :
353
+ return v1 .PleasePayState_PLEASE_PAY_STATE_UNSPECIFIED
354
+ }
355
+ }
0 commit comments