Subversion Repositories SmartDukaan

Rev

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