Subversion Repositories SmartDukaan

Rev

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