Subversion Repositories SmartDukaan

Rev

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