Subversion Repositories SmartDukaan

Rev

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