Subversion Repositories SmartDukaan

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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