Subversion Repositories SmartDukaan

Rev

Rev 24826 | Rev 24829 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
24783 amit.gupta 1
package com.smartdukaan.cron.scheduled;
2
 
24810 amit.gupta 3
import java.io.Serializable;
24783 amit.gupta 4
import java.time.LocalDate;
5
import java.util.ArrayList;
6
import java.util.Arrays;
24810 amit.gupta 7
import java.util.HashSet;
24783 amit.gupta 8
import java.util.List;
9
import java.util.Map;
24810 amit.gupta 10
import java.util.Set;
24783 amit.gupta 11
import java.util.stream.Collectors;
12
 
13
import org.apache.commons.io.output.ByteArrayOutputStream;
14
import org.springframework.beans.factory.annotation.Autowired;
15
import org.springframework.core.io.ByteArrayResource;
16
import org.springframework.mail.javamail.JavaMailSender;
17
import org.springframework.stereotype.Component;
18
 
19
import com.spice.profitmandi.common.util.FileUtil;
20
import com.spice.profitmandi.common.util.FormattingUtils;
21
import com.spice.profitmandi.common.util.Utils;
24810 amit.gupta 22
import com.spice.profitmandi.dao.entity.catalog.Scheme;
24826 amit.gupta 23
import com.spice.profitmandi.dao.entity.fofo.FofoLineItem;
24810 amit.gupta 24
import com.spice.profitmandi.dao.entity.fofo.InventoryItem;
25
import com.spice.profitmandi.dao.entity.fofo.SchemeInOut;
24783 amit.gupta 26
import com.spice.profitmandi.dao.entity.transaction.Order;
27
import com.spice.profitmandi.dao.entity.transaction.ReturnOrder;
28
import com.spice.profitmandi.dao.entity.transaction.UserWallet;
29
import com.spice.profitmandi.dao.entity.transaction.UserWalletHistory;
24810 amit.gupta 30
import com.spice.profitmandi.dao.enumuration.catalog.SchemeType;
31
import com.spice.profitmandi.dao.repository.catalog.SchemeRepository;
24783 amit.gupta 32
import com.spice.profitmandi.dao.repository.dtr.FofoStoreRepository;
24826 amit.gupta 33
import com.spice.profitmandi.dao.repository.fofo.FofoLineItemRepository;
34
import com.spice.profitmandi.dao.repository.fofo.FofoOrderItemRepository;
24810 amit.gupta 35
import com.spice.profitmandi.dao.repository.fofo.InventoryItemRepository;
36
import com.spice.profitmandi.dao.repository.fofo.SchemeInOutRepository;
24783 amit.gupta 37
import com.spice.profitmandi.dao.repository.transaction.OrderRepository;
38
import com.spice.profitmandi.dao.repository.transaction.ReturnOrderRepository;
39
import com.spice.profitmandi.dao.repository.transaction.UserWalletHistoryRepository;
40
import com.spice.profitmandi.dao.repository.transaction.UserWalletRepository;
41
import com.spice.profitmandi.service.user.RetailerService;
42
 
43
import in.shop2020.model.v1.order.OrderStatus;
44
import in.shop2020.model.v1.order.WalletReferenceType;
45
 
46
@Component
47
public class Reconciliation {
48
	@Autowired
49
	private FofoStoreRepository fofoStoreRepository;
50
	@Autowired
24826 amit.gupta 51
	private FofoOrderItemRepository fofoOrderItemRepository;
52
	@Autowired
53
	private FofoLineItemRepository fofoLineItemRepository;
54
	@Autowired
24783 amit.gupta 55
	private UserWalletRepository userWalletRepository;
56
	@Autowired
57
	private UserWalletHistoryRepository userWalletHistoryRepository;
58
	@Autowired
24810 amit.gupta 59
	private SchemeInOutRepository schemeInOutRepository;
60
	@Autowired
61
	private SchemeRepository schemeRepository;
62
	@Autowired
63
	private InventoryItemRepository inventoryRepository;
64
	@Autowired
24783 amit.gupta 65
	private RetailerService retailerService;
66
	@Autowired
67
	private ReturnOrderRepository returnOrderRepository;
68
	@Autowired
69
	private OrderRepository orderRepository;
70
	@Autowired
71
	private JavaMailSender mailSender;
72
 
73
	public void dailyReconciliation() throws Exception {
24810 amit.gupta 74
		Map<SchemeType, Set<Integer>> schemeTypeMap = schemeRepository.selectAll().stream()
75
				.collect(Collectors.groupingBy(Scheme::getType, Collectors.mapping(Scheme::getId, Collectors.toSet())));
24783 amit.gupta 76
		boolean reconciled = true;
77
		Map<Integer, String> stores = fofoStoreRepository.getStoresMap();
24810 amit.gupta 78
		List<List<? extends Serializable>> rows = new ArrayList<>();
24783 amit.gupta 79
		LocalDate yesterday = LocalDate.now().minusDays(1);
80
		Map<Integer, String> retailerNameMap = retailerService
81
				.getAllFofoRetailerIdNameMap(new ArrayList<>(stores.keySet()));
82
		for (int partnerId : stores.keySet()) {
83
			UserWallet uw = userWalletRepository.selectByRetailerId(partnerId);
84
			List<UserWalletHistory> walletHistory = userWalletHistoryRepository.selectByWalletIdAndDate(uw.getId(),
85
					yesterday);
24810 amit.gupta 86
			Map<WalletReferenceType, List<UserWalletHistory>> referenceWiseWalletHistory = walletHistory.stream()
87
					.collect(Collectors.groupingBy(x -> x.getReferenceType(), Collectors.toList()));
88
 
89
			for (Map.Entry<WalletReferenceType, List<UserWalletHistory>> entry : referenceWiseWalletHistory
90
					.entrySet()) {
91
				LocalDate dateToReconcile = yesterday;
24783 amit.gupta 92
				List<UserWalletHistory> history = entry.getValue();
24826 amit.gupta 93
				List<Serializable> reconciliation = Arrays.asList(partnerId, retailerNameMap.get(partnerId),
94
						dateToReconcile);
24810 amit.gupta 95
				Map<Integer, Integer> referenceWalletMap = entry.getValue().stream().collect(
96
						Collectors.groupingBy(x -> x.getReference(), Collectors.summingInt(x -> x.getAmount())));
97
				switch (entry.getKey()) {
98
				case PURCHASE:
99
					reconciliation.addAll(
100
							reconcileOrdersAndWallet(uw.getUserId(), dateToReconcile, referenceWalletMap, history));
101
					break;
102
				case SCHEME_IN:
103
					reconciliation.addAll(reconcileSchemeInAndWallet(uw.getUserId(), dateToReconcile,
104
							referenceWalletMap, history, schemeTypeMap.get(SchemeType.IN)));
105
					break;
106
				case SCHEME_OUT:
24826 amit.gupta 107
					reconciliation.addAll(reconcileSchemeOutAndWallet(uw.getUserId(), dateToReconcile,
108
							referenceWalletMap, history, schemeTypeMap.get(SchemeType.OUT)));
24810 amit.gupta 109
					break;
110
				default:
111
					break;
112
 
113
				}
114
				reconciled = reconciled || Boolean.TRUE.equals(reconciliation.get(0));
24783 amit.gupta 115
				rows.add(reconciliation);
116
			}
117
		}
24826 amit.gupta 118
		ByteArrayOutputStream baos = FileUtil.getCSVByteStream(Arrays.asList("PartnerId", "Store Name",
119
				"Reconciliation Date", "Purchase Reconciled", "Wallet amount consumed", "Ordered Total",
120
				"Cancelled Total", "Refunded Total", "", "Scheme In to Wallet", "Scheme In disbursed",
121
				"Scheme In rolledback", "Scheme Out to Wallet", "Scheme Out Disbursed", "Scheme Out Rolledback"), rows);
24783 amit.gupta 122
 
24810 amit.gupta 123
		Utils.sendMailWithAttachment(mailSender, new String[] { "amit.gupta@shop2020.in" }, new String[] {},
124
				reconciled ? "Reconciled Successfully" : "Reconciliation failed", "Report attached",
125
				String.format("reconciliation-%s.csv", FormattingUtils.formatDate(yesterday.atStartOfDay())),
126
				new ByteArrayResource(baos.toByteArray()));
24783 amit.gupta 127
	}
128
 
24810 amit.gupta 129
	private List<? extends Serializable> reconcileOrdersAndWallet(int fofoId, LocalDate localDate,
130
			Map<Integer, Integer> transactionsOnThatDate, List<UserWalletHistory> history) throws Exception {
24783 amit.gupta 131
 
132
		int totalWalletConsumed = 0;
133
		float cancelledAmount = 0;
134
		float returnedAmount = 0;
135
		float totalDeductedAmount = 0;
136
		for (int transactionId : transactionsOnThatDate.keySet()) {
137
			List<Order> orders = orderRepository.selectAllByTransactionId(transactionId);
138
			for (Order o : orders) {
139
				if (o.getCreateTimestamp().toLocalDate().equals(localDate)) {
140
					if (Arrays.asList(OrderStatus.PAYMENT_PENDING, OrderStatus.PAYMENT_FAILED)
141
							.contains(o.getStatus())) {
142
						cancelledAmount += o.getWalletAmount();
143
					} else if (o.getRefundTimestamp() != null
144
							&& o.getRefundTimestamp().toLocalDate().equals(localDate)) {
145
						ReturnOrder returnedOrder = returnOrderRepository.selectByOrderId(o.getId());
146
						if (returnedOrder == null) {
147
							cancelledAmount += o.getWalletAmount();
148
						} else {
149
							returnedAmount += returnedOrder.getTotalPrice();
150
						}
151
					}
152
					totalDeductedAmount += o.getWalletAmount();
153
 
154
				} else if (o.getRefundTimestamp() != null && o.getRefundTimestamp().toLocalDate().equals(localDate)) {
155
					ReturnOrder returnedOrder = returnOrderRepository.selectByOrderId(o.getId());
156
					if (returnedOrder == null) {
157
						cancelledAmount += o.getWalletAmount();
158
					} else {
159
						returnedAmount += returnedOrder.getTotalPrice();
160
					}
161
				}
162
			}
163
			totalWalletConsumed -= transactionsOnThatDate.get(transactionId);
24810 amit.gupta 164
 
24783 amit.gupta 165
		}
24810 amit.gupta 166
		boolean reconciled = Math
167
				.abs(totalWalletConsumed - (totalDeductedAmount - cancelledAmount - returnedAmount)) < 2;
24783 amit.gupta 168
 
24826 amit.gupta 169
		return Arrays.asList(reconciled, totalWalletConsumed, totalDeductedAmount, cancelledAmount, returnedAmount, "");
24783 amit.gupta 170
 
171
	}
172
 
24810 amit.gupta 173
	private List<? extends Serializable> reconcileSchemeInAndWallet(int fofoId, LocalDate localDate,
174
			Map<Integer, Integer> transactionsOnThatDate, List<UserWalletHistory> history, Set<Integer> schemeIds) {
24783 amit.gupta 175
 
24810 amit.gupta 176
		int totalSchemeInWalletCredited = 0;
177
		float schemeInAmountAdded = 0;
178
		float schemeInAmountRolledBack = 0;
179
		for (int transactionId : transactionsOnThatDate.keySet()) {
180
			List<InventoryItem> inventoryItems = inventoryRepository.selectByPurchaseId(transactionId).stream()
181
					.filter(x -> x.getSerialNumber() != null).collect(Collectors.toList());
182
			Set<Integer> inventoryItemIds = inventoryItems.stream().map(x -> x.getId()).collect(Collectors.toSet());
183
			List<SchemeInOut> sios = schemeInOutRepository.selectByInventoryItemIds(new HashSet<>(inventoryItemIds))
184
					.stream().filter(x -> schemeIds.contains(x.getSchemeId())).collect(Collectors.toList());
185
			totalSchemeInWalletCredited += transactionsOnThatDate.get(transactionId);
186
			for (SchemeInOut sio : sios) {
187
				if (sio.getCreateTimestamp().toLocalDate().equals(localDate)) {
188
					schemeInAmountAdded += sio.getAmount();
189
				}
24828 amit.gupta 190
				if (sio.getRolledBackTimestamp() != null && sio.getRolledBackTimestamp().toLocalDate().equals(localDate)) {
24826 amit.gupta 191
					schemeInAmountRolledBack += sio.getAmount();
24810 amit.gupta 192
				}
193
			}
194
 
195
		}
24826 amit.gupta 196
		boolean reconciled = Math
197
				.abs(totalSchemeInWalletCredited - (schemeInAmountAdded - schemeInAmountRolledBack)) < 5;
24810 amit.gupta 198
 
24826 amit.gupta 199
		return Arrays.asList(reconciled, totalSchemeInWalletCredited, schemeInAmountAdded, schemeInAmountRolledBack,
200
				"");
24810 amit.gupta 201
 
24783 amit.gupta 202
	}
203
 
24826 amit.gupta 204
	private List<? extends Serializable> reconcileSchemeOutAndWallet(int fofoId, LocalDate localDate,
205
			Map<Integer, Integer> transactionsOnThatDate, List<UserWalletHistory> history, Set<Integer> schemeIds) {
206
		int totalSchemeOutWalletCredited = 0;
207
		float schemeOutAmountAdded = 0;
208
		float schemeOutAmountRolledBack = 0;
209
		for (int fofoOrderId : transactionsOnThatDate.keySet()) {
210
			Set<Integer> fofoOrderItemIds = fofoOrderItemRepository.selectByOrderId(fofoOrderId).stream()
211
					.map(x -> x.getId()).collect(Collectors.toSet());
212
			List<FofoLineItem> fofoLineItems = fofoLineItemRepository.selectByFofoOrderItemIds(fofoOrderItemIds);
213
			Set<Integer> inventoryItemIds = fofoLineItems.stream().map(x -> x.getInventoryItemId())
214
					.collect(Collectors.toSet());
215
			List<SchemeInOut> sios = schemeInOutRepository.selectByInventoryItemIds(new HashSet<>(inventoryItemIds))
216
					.stream().filter(x -> schemeIds.contains(x.getSchemeId())).collect(Collectors.toList());
217
			totalSchemeOutWalletCredited += transactionsOnThatDate.get(fofoOrderId);
218
			for (SchemeInOut sio : sios) {
219
				if (sio.getCreateTimestamp().toLocalDate().equals(localDate)) {
220
					schemeOutAmountAdded += sio.getAmount();
221
				}
24828 amit.gupta 222
				if (sio.getRolledBackTimestamp() != null && sio.getRolledBackTimestamp().toLocalDate().equals(localDate)) {
24826 amit.gupta 223
					schemeOutAmountRolledBack += sio.getAmount();
224
				}
225
			}
226
		}
227
		boolean reconciled = Math
228
				.abs(totalSchemeOutWalletCredited - (schemeOutAmountAdded - schemeOutAmountRolledBack)) < 5;
229
		return Arrays.asList(reconciled, totalSchemeOutWalletCredited, schemeOutAmountAdded, schemeOutAmountRolledBack,
230
				"");
24783 amit.gupta 231
	}
232
}