Subversion Repositories SmartDukaan

Rev

Rev 2137 | Rev 2199 | 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;
5
import in.shop2020.model.v1.order.Transaction;
6
import in.shop2020.model.v1.order.TransactionServiceException;
7
import in.shop2020.model.v1.order.TransactionStatus;
8
import in.shop2020.model.v1.user.Cart;
9
import in.shop2020.model.v1.user.Line;
1981 varun.gupt 10
import in.shop2020.model.v1.user.PromotionException;
1905 chandransh 11
import in.shop2020.model.v1.user.ShoppingCartException;
1981 varun.gupt 12
import in.shop2020.model.v1.user.UserContextService;
2137 chandransh 13
import in.shop2020.payments.Payment;
1905 chandransh 14
import in.shop2020.payments.PaymentException;
15
import in.shop2020.serving.utils.Utils;
16
import in.shop2020.thrift.clients.PaymentServiceClient;
1981 varun.gupt 17
import in.shop2020.thrift.clients.PromotionServiceClient;
1905 chandransh 18
import in.shop2020.thrift.clients.TransactionServiceClient;
19
import in.shop2020.thrift.clients.UserContextServiceClient;
20
 
21
import java.util.HashMap;
22
import java.util.List;
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);
40
 
41
	private long paymentId;
42
	private double amount;
43
 
44
	public long getPaymentId() {
45
		return paymentId;
46
	}
47
 
48
	public double getAmount() {
49
		return amount;
50
	}
51
 
52
	/**
53
	 * Creates a payment for the given cart of the given user for the given
54
	 * transaction. Stores the id of the newly created payment and the amount
55
	 * for which this payment was created. They can be retrieved later on using
56
	 * {@link #getPaymentId()}getPaymentId() and {@link #getAmount()}getAmount()
57
	 * methods respectively later on.
58
	 * 
59
	 * @param currentCartId
60
	 *            The cart for which the payment object has to be created.
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
	 */
69
	public boolean createPayment(long currentCartId, long userId, long txnId, int gatewayId){
70
		PaymentServiceClient paymentServiceClient = null;
71
		try {
72
			paymentServiceClient = new PaymentServiceClient();
73
		} catch (Exception e) {
74
			log.error("Error while getting payment client");
75
			e.printStackTrace();
76
			return PAYMENT_NOT_CREATED;
77
		}
78
 
79
		try {
80
			amount = calculatePaymentAmount(currentCartId);
81
		} catch (ShoppingCartException e1) {
82
			log.error("Not able to fetch payment amount from cart id." + e1.getId() + e1.getMessage());
83
			e1.printStackTrace();
84
			return PAYMENT_NOT_CREATED;
85
		} catch (TException e1) {
86
			log.error("Not able to fetch payment amount." + e1.getMessage());
87
			e1.printStackTrace();
88
			return PAYMENT_NOT_CREATED;
89
		}
90
 
91
		try {
2137 chandransh 92
			paymentId = paymentServiceClient.getClient().createPayment(userId, amount, gatewayId, txnId);
93
			// This is being done to ensure that the amount which we pass on to
94
			// the PGs is same as what we have in the database.
95
			Payment payment = paymentServiceClient.getClient().getPayment(paymentId);
96
			amount = payment.getAmount();
1905 chandransh 97
		} catch (PaymentException e1) {
98
			log.error("Not able to create payment object." + e1.getError_code() + e1.getMessage());
99
			e1.printStackTrace();
100
			return PAYMENT_NOT_CREATED;
101
		} catch (TException e) {
102
			log.error("Not able to create payment object." + e.getMessage());
103
			e.printStackTrace();
104
			return PAYMENT_NOT_CREATED;
105
		}
106
 
107
		return true;
108
	}
109
 
110
	/**
111
	 * Marks the given transaction as in process. Once the transaction is marked
112
	 * as successful, the items in the cart for which this transaction was
113
	 * processed are removed from the cart.<br>
114
	 * Please note that it's possible that a user has added items to the cart
115
	 * and so it's not possible to simply wipe out their cart.<br>
116
	 * Again, it's important to ensure that we remove only as much quantity of
117
	 * items as for which the order was processed.
118
	 * 
119
	 * @param txnId The transaction which should be marked as successful.
120
	 * @param userServiceClient A user context service client to use.
121
	 * @param transactionServiceClient A transaction service client to use.
122
	 */
123
	public static void processSuccessfulTxn(long txnId, UserContextServiceClient userServiceClient, TransactionServiceClient transactionServiceClient) {
124
		Transaction transaction = null;
125
		Map<Long,Double> items = new HashMap<Long, Double>();
126
		try {
127
			in.shop2020.model.v1.order.TransactionService.Client transactionClient = transactionServiceClient.getClient();
128
			transactionClient.changeTransactionStatus(txnId, TransactionStatus.IN_PROCESS, "Payment received for the order");
129
			transaction = transactionClient.getTransaction(txnId);
130
			for(Order order: transaction.getOrders()){
131
				for(LineItem lineitem: order.getLineitems()){
132
					Long itemId = lineitem.getItem_id();
133
					Double quantity = items.get(itemId);
134
					if(quantity==null){
135
						quantity = lineitem.getQuantity();
136
					}
137
					else{
138
						quantity= quantity + lineitem.getQuantity();
139
					}
140
					items.put(itemId, quantity);
141
				}
142
			}
143
		} catch (TException e1) {
144
			log.error("Unable to update status of transaction. Thrift Exception" + e1.getMessage());
145
			e1.printStackTrace();
146
		} catch (TransactionServiceException e) {
147
			log.error("Unable to update status of transaction. Thrift Exception" + e.getErrorCode() + e.getMessage());
148
			e.printStackTrace();
149
		}
2009 varun.gupt 150
 
151
        try   {
152
            // Tracking Coupon Usage 
153
            UserContextService.Client userClient = userServiceClient.getClient();
154
            Cart cart = userClient.getCart(transaction.getShoppingCartid());
155
 
156
            PromotionServiceClient promotionServiceClient = new PromotionServiceClient();
157
            String couponCode = cart.getCouponCode();
158
 
159
            if (couponCode != null && !couponCode.isEmpty()) {
160
                promotionServiceClient.getClient().trackCouponUsage(couponCode, txnId, transaction.getCustomer_id());
161
            }
162
        } catch (ShoppingCartException e) {
163
            log.error("Error occurred in reading CardId for transaction");
164
            e.printStackTrace();
165
        } catch (PromotionException e) {
166
            log.error("Promotion Exception: " + e.getMessage());
167
            e.printStackTrace();
168
        } catch (TException e)  {
169
            log.error("Transport from Promotion Service failed");
170
            e.printStackTrace();
171
        } catch (Exception e) {
172
            e.printStackTrace();
173
        }
174
 
1905 chandransh 175
		try {
176
			//TODO Optimize the function to send less amount of data over network
177
			log.info("Transaction shopping cart id is: " + transaction.getShoppingCartid());
178
			log.info("Items to restr in cart are: " + items );
1981 varun.gupt 179
 
180
            userServiceClient.getClient().resetCart(transaction.getShoppingCartid(), items);
181
 
1905 chandransh 182
		}catch (TException e) {
183
			log.error("Error while updating information in payment database.");
184
			e.printStackTrace();
185
			//FIXME Even we get exception we should sent url back to payment gateway. And some thing back channel should be done
186
 
187
		} catch (ShoppingCartException e) {
188
			log.error("Error while reseting the cart in cart database.");
189
			e.printStackTrace();
1981 varun.gupt 190
		}catch (Exception e) {
191
            // TODO: handle exception
192
        }
1905 chandransh 193
	}
194
 
195
	/**
196
	 * Enqueues the transaction successful email, containing transaction info,
197
	 * to be sent later by batch job.
198
	 * 
199
	 * @param transactionClient
200
	 */
201
	public static void sendTxnEmail(long txnId, TransactionServiceClient transactionServiceClient) {
202
		in.shop2020.model.v1.order.TransactionService.Client transactionClient = transactionServiceClient.getClient();
203
		try {
204
			transactionClient.enqueueTransactionInfoEmail(txnId);
205
		} catch (Exception e) {
206
			log.error("Error while adding email to dispatch queue.");
207
			e.printStackTrace();
208
		}
209
	}
210
 
211
	/**
212
	 * Marks a transaction as well as all its orders as failed.
213
	 * 
214
	 * @param txnId
215
	 *            The id of the transaction which has to be marked as failed.
216
	 * @param transactionServiceClient
217
	 */
218
	public static void processFailedTxn(long txnId, TransactionServiceClient transactionServiceClient) {
219
		try {
220
			in.shop2020.model.v1.order.TransactionService.Client transactionClient = transactionServiceClient.getClient();
221
			transactionClient.changeTransactionStatus(txnId, TransactionStatus.FAILED, "Payment failed for the transaction.");
222
		} catch(TException e){
223
			log.error("Thrift exception while getting information from transaction service.");
224
			e.printStackTrace();
225
		} catch (TransactionServiceException e) {
226
			log.error("Error while updating status information in transaction database.");
227
			e.printStackTrace();
228
		}
229
	}
230
 
231
	/**
232
	 * Calculates the amount for the payment required for the given cart.
233
	 * 
234
	 * @param cartId
235
	 *            Id of the cart for which this payment amount has to be
236
	 *            calculated.
237
	 * @return The total amount for which a payment should be created.
238
	 * @throws ShoppingCartException
239
	 *             If no cart can be found for the given id.
240
	 * @throws TException
241
	 */
242
	private double calculatePaymentAmount(long cartId) throws ShoppingCartException, TException{
243
		double totalAmount = 0;
244
		Cart cart;
245
		UserContextServiceClient userContextServiceClient = null;
246
		try {
247
			userContextServiceClient = new UserContextServiceClient();
248
		} catch (Exception e) {
249
			e.printStackTrace();
250
		}
251
		in.shop2020.model.v1.user.UserContextService.Client userClient = userContextServiceClient.getClient();
252
		cart = userClient.getCart(cartId);
1981 varun.gupt 253
 
254
		if(cart.getCouponCode() == null || cart.getDiscountedPrice() == 0.0)  {
255
		    List<Line> lineItems = cart.getLines(); 
256
 
257
	        for (Line line : lineItems) {
258
	            long productId = line.getItemId();
259
	            // FIXME: It's expensive to get the price of each item from the
260
	            // catalog service. We maintain the pricing info in the line items
261
	            // themselves now.
262
	            totalAmount =  totalAmount + line.getQuantity() * Utils.getItemPrice(productId);
263
	        }
264
		} else    {
265
		    totalAmount = cart.getDiscountedPrice();
1905 chandransh 266
		}
1981 varun.gupt 267
 
1905 chandransh 268
		return totalAmount;
269
	}
270
 
271
	// TODO: The service client parameters are unnecessary but initializing them
272
	// again when the caller has the necessary references has a performance
273
	// overhead. Need to think more about this.
274
}