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