Subversion Repositories SmartDukaan

Rev

Rev 7293 | Rev 7953 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1905 chandransh 1
package in.shop2020.serving.services;
2
 
3
import in.shop2020.model.v1.order.LineItem;
4
import in.shop2020.model.v1.order.Order;
7293 anupam.sin 5
import in.shop2020.model.v1.order.OrderSource;
6050 anupam.sin 6
import in.shop2020.model.v1.order.RechargeOrder;
1905 chandransh 7
import in.shop2020.model.v1.order.Transaction;
8
import in.shop2020.model.v1.order.TransactionServiceException;
9
import in.shop2020.model.v1.order.TransactionStatus;
5527 anupam.sin 10
import in.shop2020.model.v1.order.OrderType;
1981 varun.gupt 11
import in.shop2020.model.v1.user.PromotionException;
1905 chandransh 12
import in.shop2020.model.v1.user.ShoppingCartException;
5527 anupam.sin 13
import in.shop2020.logistics.PickUpType;
2137 chandransh 14
import in.shop2020.payments.Payment;
1905 chandransh 15
import in.shop2020.payments.PaymentException;
6318 rajveer 16
import in.shop2020.payments.PaymentStatus;
3126 rajveer 17
import in.shop2020.thrift.clients.PaymentClient;
18
import in.shop2020.thrift.clients.PromotionClient;
19
import in.shop2020.thrift.clients.TransactionClient;
20
import in.shop2020.thrift.clients.UserClient;
1905 chandransh 21
 
22
import java.util.HashMap;
23
import java.util.Map;
24
 
25
import org.apache.log4j.Logger;
26
import org.apache.thrift.TException;
27
 
28
/**
29
 * This class has methods to be used to process non-gateway-specific aspects of
30
 * payments and transactions.
31
 * 
32
 * @author Chandranshu
33
 * 
34
 */
35
public class CommonPaymentService {
36
 
37
	private static final boolean PAYMENT_NOT_CREATED = false;
38
 
39
	private static Logger log = Logger.getLogger(Class.class);
6318 rajveer 40
	private static long gvGatewayId = 9;
1905 chandransh 41
 
42
	private long paymentId;
43
	private double amount;
6318 rajveer 44
	private boolean isGv = false;
45
	private double gvAmount = 0;
1905 chandransh 46
 
47
	public long getPaymentId() {
48
		return paymentId;
49
	}
50
 
51
	public double getAmount() {
52
		return amount;
53
	}
54
 
55
	/**
56
	 * Creates a payment for the given cart of the given user for the given
57
	 * transaction. Stores the id of the newly created payment and the amount
58
	 * for which this payment was created. They can be retrieved later on using
59
	 * {@link #getPaymentId()}getPaymentId() and {@link #getAmount()}getAmount()
60
	 * methods respectively later on.
61
	 * 
62
	 * @param userId
63
	 *            The user for whom the payment has to be created.
64
	 * @param txnId
65
	 *            The transaction against which the payment has to be created.
66
	 * @param gatewayId
67
	 * @return True if the payment object is successfully created, False
68
	 *         otherwise.
69
	 */
6390 rajveer 70
	public boolean createPayment(long userId, long txnId, int gatewayId){
3126 rajveer 71
		PaymentClient paymentServiceClient = null;
6318 rajveer 72
		in.shop2020.payments.PaymentService.Client pclient;
1905 chandransh 73
		try {
3126 rajveer 74
			paymentServiceClient = new PaymentClient();
6318 rajveer 75
			pclient = paymentServiceClient.getClient();
1905 chandransh 76
		} catch (Exception e) {
2199 chandransh 77
			log.error("Error while getting payment client", e);
1905 chandransh 78
			return PAYMENT_NOT_CREATED;
79
		}
80
 
81
		try {
6390 rajveer 82
			amount = calculatePaymentAmount(txnId);
83
		} catch (TransactionServiceException e1) {
84
			log.error("Unable to fetch payment amount from txn id.", e1);
1905 chandransh 85
			return PAYMENT_NOT_CREATED;
86
		} catch (TException e1) {
2199 chandransh 87
			log.error("Unable to fetch payment amount.", e1);
1905 chandransh 88
			return PAYMENT_NOT_CREATED;
89
		}
90
 
91
		try {
6318 rajveer 92
			if(isGv){
93
				paymentId = pclient.createPayment(userId, gvAmount, gvGatewayId, txnId, false);
94
				pclient.updatePaymentDetails(paymentId, "", "", "SUCCESS", "Payment Received", "", "", "", "", PaymentStatus.SUCCESS, "", null);
95
			}
6050 anupam.sin 96
			paymentId = paymentServiceClient.getClient().createPayment(userId, amount, gatewayId, txnId, false);
2137 chandransh 97
			// This is being done to ensure that the amount which we pass on to
98
			// the PGs is same as what we have in the database.
99
			Payment payment = paymentServiceClient.getClient().getPayment(paymentId);
100
			amount = payment.getAmount();
1905 chandransh 101
		} catch (PaymentException e1) {
2199 chandransh 102
			log.error("Unable to create payment object.", e1);
1905 chandransh 103
			return PAYMENT_NOT_CREATED;
104
		} catch (TException e) {
2199 chandransh 105
			log.error("Not able to create payment object.", e);
1905 chandransh 106
			return PAYMENT_NOT_CREATED;
107
		}
108
 
109
		return true;
110
	}
111
 
2199 chandransh 112
	// TODO: The service client parameters in the processSuccessfulTxn et al are
113
	// unnecessary but initializing them again when the caller has the necessary
114
	// references has a performance overhead. Need to think more about this.
115
 
1905 chandransh 116
	/**
2199 chandransh 117
	 * Processes a successful transaction by:
118
	 * <ol>
3063 chandransh 119
	 * <li>Marking the given transaction as 'authorized'.</li>
2199 chandransh 120
	 * <li>Removing the items in the cart for which the given transaction was
121
	 * processed.</li>
122
	 * <li>Marking the coupon associated with this transaction, if any, as used
123
	 * for this user.</li>
124
	 * <li>Queuing the transaction successful email, containing transaction
125
	 * info, to be sent later by a batch job.</li>
126
	 * </ol>
127
	 * <br>
1905 chandransh 128
	 * Please note that it's possible that a user has added items to the cart
2199 chandransh 129
	 * and so it's not possible to simply wipe out their cart. Therefore, it's
130
	 * important to ensure that we remove only as much quantity of items as for
131
	 * which the order was processed.
1905 chandransh 132
	 * 
2199 chandransh 133
	 * @param txnId
134
	 *            The transaction which should be marked as successful.
135
	 * @param userServiceClient
136
	 *            A user context service client to use.
137
	 * @param transactionServiceClient
138
	 *            A transaction service client to use.
4246 rajveer 139
	 * @param isFlagged
140
	 * 			  If payment is flagged it will be true else false 
1905 chandransh 141
	 */
4246 rajveer 142
	public static void processSuccessfulTxn(long txnId, UserClient userServiceClient, TransactionClient transactionServiceClient, boolean isFlagged) {
1905 chandransh 143
		Transaction transaction = null;
4246 rajveer 144
		TransactionStatus tStatus = TransactionStatus.AUTHORIZED;
145
        String description = "Payment authorized for the order";
146
		// if flag is set, status to be changed to flagged
147
		if(isFlagged){
148
			tStatus = TransactionStatus.FLAGGED;
149
			description = "Payment flagged for the order";
150
		}
1905 chandransh 151
		try {
152
			in.shop2020.model.v1.order.TransactionService.Client transactionClient = transactionServiceClient.getClient();
7293 anupam.sin 153
			transactionClient.changeTransactionStatus(txnId, tStatus, description, PickUpType.COURIER.getValue(), OrderType.B2C, OrderSource.WEBSITE);
1905 chandransh 154
			transaction = transactionClient.getTransaction(txnId);
2199 chandransh 155
			transactionClient.enqueueTransactionInfoEmail(txnId);
1905 chandransh 156
		} catch (TException e1) {
2199 chandransh 157
			log.error("Unable to update status of transaction. Thrift Exception:", e1);
1905 chandransh 158
		} catch (TransactionServiceException e) {
2199 chandransh 159
			log.error("Unable to update status of transaction. Thrift Exception: ", e);
1905 chandransh 160
		}
2219 varun.gupt 161
		trackCouponUsage(transaction);
2199 chandransh 162
        resetCart(transaction, userServiceClient);
1905 chandransh 163
	}
164
 
165
	/**
166
	 * Marks a transaction as well as all its orders as failed.
167
	 * 
168
	 * @param txnId
169
	 *            The id of the transaction which has to be marked as failed.
170
	 * @param transactionServiceClient
171
	 */
3126 rajveer 172
	public static void processFailedTxn(long txnId, TransactionClient transactionServiceClient) {
1905 chandransh 173
		try {
174
			in.shop2020.model.v1.order.TransactionService.Client transactionClient = transactionServiceClient.getClient();
7293 anupam.sin 175
			transactionClient.changeTransactionStatus(txnId, TransactionStatus.FAILED, "Payment failed for the transaction.", PickUpType.COURIER.getValue(), OrderType.B2C, OrderSource.WEBSITE);
1905 chandransh 176
		} catch(TException e){
2199 chandransh 177
			log.error("Thrift exception while getting information from transaction service.", e);
1905 chandransh 178
		} catch (TransactionServiceException e) {
2199 chandransh 179
			log.error("Error while updating status information in transaction database.", e);
1905 chandransh 180
		}
181
	}
182
 
3063 chandransh 183
    /**
184
     * Processes a COD transaction by:
185
     * <ol>
186
     * <li>Setting the COD flag of all the orders and moving them to the INIT
187
     * state.
188
     * <li>Marking the given transaction to be in COD_IN_PROCESS state
189
     * <li>Marking the coupon associated with this transaction, if any, as used
190
     * for this user.</li>
191
     * <li>Queuing the transaction successful email, containing transaction
192
     * info, to be sent later by a batch job.</li>
193
     * </ol>
194
     * <br>
195
     * Please note that it's possible that a user has added items to the cart
196
     * and so it's not possible to simply wipe out their cart. Therefore, it's
197
     * important to ensure that we remove only as much quantity of items as for
198
     * which the order was processed.
199
     * 
200
     * @param txnId
201
     *            The COD transaction which should be marked as verification
202
     *            pending.
203
     */
204
	public static void processCodTxn(long txnId){
205
        try {            
3126 rajveer 206
            TransactionClient transactionServiceClient = new TransactionClient();
3063 chandransh 207
            in.shop2020.model.v1.order.TransactionService.Client transactionClient = transactionServiceClient.getClient();
7293 anupam.sin 208
            transactionClient.changeTransactionStatus(txnId, TransactionStatus.COD_IN_PROCESS, "COD payment awaited", PickUpType.COURIER.getValue(), OrderType.B2C, OrderSource.WEBSITE);
3063 chandransh 209
            Transaction transaction = transactionClient.getTransaction(txnId);
210
            transactionClient.enqueueTransactionInfoEmail(txnId);
211
 
3126 rajveer 212
            UserClient userServiceClient = new UserClient();
3063 chandransh 213
            trackCouponUsage(transaction);
214
            resetCart(transaction, userServiceClient);
215
        } catch (TException e1) {
216
            log.error("Unable to update status of transaction. Thrift Exception:", e1);
217
        } catch (TransactionServiceException e) {
218
            log.error("Unable to update status of transaction. Thrift Exception: ", e);
219
        } catch (Exception e) {
220
            log.error("Unable to update status of transaction. Thrift Exception: ", e);
221
        }
222
	}
223
 
7862 anupam.sin 224
	public static void processCouponTxn(long txnId){
225
        try {            
226
            TransactionClient transactionServiceClient = new TransactionClient();
227
            in.shop2020.model.v1.order.TransactionService.Client transactionClient = transactionServiceClient.getClient();
228
            transactionClient.changeTransactionStatus(txnId, TransactionStatus.AUTHORIZED, "Payment by coupon successful", PickUpType.COURIER.getValue(), OrderType.B2C, OrderSource.WEBSITE);
229
            Transaction transaction = transactionClient.getTransaction(txnId);
230
            UserClient userServiceClient = new UserClient();
231
            trackCouponUsage(transaction);
232
            resetCart(transaction, userServiceClient);
233
        } catch (TException e1) {
234
            log.error("Unable to update status of transaction. Thrift Exception:", e1);
235
        } catch (TransactionServiceException e) {
236
            log.error("Unable to update status of transaction. Thrift Exception: ", e);
237
        } catch (Exception e) {
238
            log.error("Unable to update status of transaction. Thrift Exception: ", e);
239
        }
240
    }
241
 
1905 chandransh 242
	/**
6390 rajveer 243
	 * Calculates the amount for the payment required for the given transaction.
1905 chandransh 244
	 * 
6390 rajveer 245
	 * @param txnId
246
	 *            Id of the transaction for which this payment amount has to be
1905 chandransh 247
	 *            calculated.
248
	 * @return The total amount for which a payment should be created.
6390 rajveer 249
	 * @throws TransactionServiceException 
1905 chandransh 250
	 * @throws TException
251
	 */
6390 rajveer 252
	private double calculatePaymentAmount(long txnId) throws TransactionServiceException, TException{
1905 chandransh 253
		double totalAmount = 0;
6390 rajveer 254
		TransactionClient transactionServiceClient = null;
1905 chandransh 255
		try {
6390 rajveer 256
			transactionServiceClient = new TransactionClient();
1905 chandransh 257
		} catch (Exception e) {
2942 chandransh 258
			log.error("Unable to initialize user context service client", e);
6390 rajveer 259
			throw new TransactionServiceException(100, "Unable to initialize the user service client");
1905 chandransh 260
		}
6390 rajveer 261
		in.shop2020.model.v1.order.TransactionService.Client tClient = transactionServiceClient.getClient();
262
		Transaction transaction = tClient.getTransaction(txnId);
6412 rajveer 263
		Map<Long, Double> miscCharges = tClient.getMiscCharges(txnId);
264
		System.out.println(miscCharges);
6415 rajveer 265
		if(miscCharges != null & !miscCharges.isEmpty()){
266
			totalAmount = totalAmount + miscCharges.get(1L);
1905 chandransh 267
		}
6390 rajveer 268
		for(Order order: transaction.getOrders()){
269
			totalAmount = totalAmount + order.getTotal_amount();
270
			gvAmount = gvAmount + order.getGvAmount();
271
		}
272
		if(gvAmount>0){
273
			isGv = true;	
274
		}
6431 rajveer 275
		return (totalAmount-gvAmount);
1905 chandransh 276
	}
277
 
2199 chandransh 278
	/**
279
	 * Removes the items processed through the given transaction from the
280
	 * shopping cart.
281
	 * 
282
	 * @param transaction
283
	 *            The transaction whose items have to be removed from the
284
	 *            shopping cart.
285
	 * @param userServiceClient
286
	 */
3126 rajveer 287
	private static void resetCart(Transaction transaction, UserClient userServiceClient) {
2199 chandransh 288
		Map<Long, Double> items = new HashMap<Long, Double>();
289
		for(Order order: transaction.getOrders()){
290
			for(LineItem lineitem: order.getLineitems()){
291
				Long itemId = lineitem.getItem_id();
292
				Double quantity = items.get(itemId);
293
				if(quantity==null){
294
					quantity = lineitem.getQuantity();
295
				} else {
296
					quantity= quantity + lineitem.getQuantity();
297
				}
298
				items.put(itemId, quantity);
299
			}
300
		}
301
 
3063 chandransh 302
		log.debug("Items to reset in cart are: " + items);
2199 chandransh 303
 
304
		try {
305
			//TODO Optimize the function to send less data over the wire
306
            userServiceClient.getClient().resetCart(transaction.getShoppingCartid(), items);
307
		}catch (TException e) {
308
			log.error("Error while updating information in payment database.", e);
309
		} catch (ShoppingCartException e) {
310
			log.error("Error while reseting the cart in cart database.", e);
311
		}catch (Exception e) {
312
			log.error("Unexpected exception", e);
313
        }
314
	}
315
 
316
	/**
317
	 * Mark the coupon associated with the given transaction as used.
318
	 * 
319
	 * @param transaction
320
	 *            The transaction to track coupon for.
321
	 * 
322
	 * @param userServiceClient
323
	 *            The user service client instance to use.
324
	 */
2219 varun.gupt 325
	private static void trackCouponUsage(Transaction transaction) {
2199 chandransh 326
        try {
2219 varun.gupt 327
            String couponCode = transaction.getCoupon_code();
328
 
2199 chandransh 329
            if (couponCode != null && !couponCode.isEmpty()) {
3126 rajveer 330
            	PromotionClient promotionServiceClient = new PromotionClient();
2199 chandransh 331
                promotionServiceClient.getClient().trackCouponUsage(couponCode, transaction.getId(), transaction.getCustomer_id());
332
            }
333
        } catch (PromotionException e) {
334
            log.error("Promotion Exception: " + e);
335
        } catch (TException e)  {
336
            log.error("Transport from Promotion Service failed:", e);
337
        } catch (Exception e) {
338
            log.error("Unexpected exception:", e);
339
        }
340
	}
6050 anupam.sin 341
 
342
    public boolean createPayment(RechargeOrder rechargeOrder, int gatewayId) {
343
        PaymentClient paymentServiceClient = null;
344
        try {
345
            paymentServiceClient = new PaymentClient();
346
        } catch (Exception e) {
347
            log.error("Error while getting payment client", e);
348
            return PAYMENT_NOT_CREATED;
349
        }
350
 
6443 anupam.sin 351
        amount = rechargeOrder.getTotalAmount() - rechargeOrder.getWalletAmount() - rechargeOrder.getCouponAmount();
6050 anupam.sin 352
 
353
        try {
354
            paymentId = paymentServiceClient.getClient().createPayment(rechargeOrder.getUserId(), amount, gatewayId, rechargeOrder.getTransactionId(), true);
355
            // This is being done to ensure that the amount which we pass on to
356
            // the PGs is same as what we have in the database.
357
            Payment payment = paymentServiceClient.getClient().getPayment(paymentId);
358
            amount = payment.getAmount();
359
        } catch (PaymentException e1) {
360
            log.error("Unable to create payment object.", e1);
361
            return PAYMENT_NOT_CREATED;
362
        } catch (TException e) {
363
            log.error("Not able to create payment object.", e);
364
            return PAYMENT_NOT_CREATED;
365
        }
366
 
367
        return true;
368
 
369
    }
6415 rajveer 370
    public static void main(String[] args) {
371
    	Map<Long, Double> miscCharges = new HashMap<Long, Double>();
372
    	miscCharges.put(1L, 3.988);
373
    	System.out.println(miscCharges);
374
		if(miscCharges != null & !miscCharges.isEmpty()){
375
			System.out.println( miscCharges.get(1L));;
376
		}
377
	}
1905 chandransh 378
}