Subversion Repositories SmartDukaan

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
22859 ashik.ali 1
package com.spice.profitmandi.service.sale;
2
 
3
import java.time.DateTimeException;
4
import java.time.LocalDate;
5
import java.util.ArrayList;
6
import java.util.HashMap;
7
import java.util.HashSet;
8
import java.util.Iterator;
9
import java.util.List;
10
import java.util.Map;
11
import java.util.Set;
12
 
13
import org.json.JSONObject;
14
import org.slf4j.Logger;
15
import org.slf4j.LoggerFactory;
16
import org.springframework.beans.factory.annotation.Autowired;
17
import org.springframework.stereotype.Component;
18
 
19
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
20
import com.spice.profitmandi.common.model.CartFofo;
21
import com.spice.profitmandi.common.model.CreateOrderRequest;
22
import com.spice.profitmandi.common.model.CustomAddress;
23
import com.spice.profitmandi.common.model.CustomCustomer;
24
import com.spice.profitmandi.common.model.CustomFofoOrderItem;
25
import com.spice.profitmandi.common.model.CustomInsurancePolicy;
26
import com.spice.profitmandi.common.model.CustomOrderItem;
27
import com.spice.profitmandi.common.model.CustomPaymentOption;
28
import com.spice.profitmandi.common.model.CustomRetailer;
29
import com.spice.profitmandi.common.model.GadgetCopsInsuranceModel;
30
import com.spice.profitmandi.common.model.ItemIdQuantityAvailability;
31
import com.spice.profitmandi.common.model.PdfModel;
32
import com.spice.profitmandi.common.model.PriceModel;
33
import com.spice.profitmandi.common.model.ProfitMandiConstants;
34
import com.spice.profitmandi.common.model.Quantity;
35
import com.spice.profitmandi.common.model.SerialNumberDetail;
36
import com.spice.profitmandi.common.util.InsuranceUtils;
37
import com.spice.profitmandi.common.util.StringUtils;
38
import com.spice.profitmandi.dao.entity.catalog.Item;
39
import com.spice.profitmandi.dao.entity.dtr.GadgetCopsInsuranceCalc;
40
import com.spice.profitmandi.dao.entity.dtr.InsurancePolicy;
41
import com.spice.profitmandi.dao.entity.dtr.InsuranceProvider;
42
import com.spice.profitmandi.dao.entity.dtr.PolicyNumberGenerationSequence;
43
import com.spice.profitmandi.dao.entity.dtr.Retailer;
44
import com.spice.profitmandi.dao.entity.dtr.User;
45
import com.spice.profitmandi.dao.entity.fofo.CurrentInventorySnapshot;
46
import com.spice.profitmandi.dao.entity.fofo.Customer;
47
import com.spice.profitmandi.dao.entity.fofo.CustomerAddress;
48
import com.spice.profitmandi.dao.entity.fofo.FofoLineItem;
49
import com.spice.profitmandi.dao.entity.fofo.FofoOrder;
50
import com.spice.profitmandi.dao.entity.fofo.FofoOrderItem;
51
import com.spice.profitmandi.dao.entity.fofo.InventoryItem;
52
import com.spice.profitmandi.dao.entity.fofo.InvoiceNumberGenerationSequence;
53
import com.spice.profitmandi.dao.entity.fofo.PaymentOption;
54
import com.spice.profitmandi.dao.entity.fofo.ScanRecord;
55
import com.spice.profitmandi.dao.entity.user.Address;
56
import com.spice.profitmandi.dao.entity.user.Counter;
57
import com.spice.profitmandi.dao.entity.user.PrivateDealUser;
58
import com.spice.profitmandi.dao.enumuration.fofo.PaymentOptionType;
59
import com.spice.profitmandi.dao.enumuration.fofo.ScanType;
60
import com.spice.profitmandi.dao.repository.catalog.ItemRepository;
61
import com.spice.profitmandi.dao.repository.dtr.InsurancePolicyRepository;
62
import com.spice.profitmandi.dao.repository.dtr.InsuranceProviderRepository;
63
import com.spice.profitmandi.dao.repository.dtr.PolicyNumberGenerationSequenceRepository;
64
import com.spice.profitmandi.dao.repository.dtr.RetailerRegisteredAddressRepository;
65
import com.spice.profitmandi.dao.repository.dtr.RetailerRepository;
66
import com.spice.profitmandi.dao.repository.dtr.UserAccountRepository;
67
import com.spice.profitmandi.dao.repository.dtr.UserRepository;
68
import com.spice.profitmandi.dao.repository.fofo.CurrentInventorySnapshotRepository;
69
import com.spice.profitmandi.dao.repository.fofo.CustomerAddressRepository;
70
import com.spice.profitmandi.dao.repository.fofo.CustomerRepository;
71
import com.spice.profitmandi.dao.repository.fofo.FofoLineItemRepository;
72
import com.spice.profitmandi.dao.repository.fofo.FofoOrderItemRepository;
73
import com.spice.profitmandi.dao.repository.fofo.FofoOrderRepository;
74
import com.spice.profitmandi.dao.repository.fofo.InventoryItemRepository;
75
import com.spice.profitmandi.dao.repository.fofo.InvoiceNumberGenerationSequenceRepository;
76
import com.spice.profitmandi.dao.repository.fofo.PaymentOptionRepository;
77
import com.spice.profitmandi.dao.repository.fofo.ScanRecordRepository;
78
import com.spice.profitmandi.dao.repository.user.AddressRepository;
79
import com.spice.profitmandi.dao.repository.user.CounterRepository;
80
import com.spice.profitmandi.dao.repository.user.PrivateDealUserRepository;
81
import com.spice.profitmandi.service.pricing.PricingService;
82
import com.spice.profitmandi.service.scheme.SchemeService;
83
 
84
import in.shop2020.model.v1.catalog.ItemType;
85
 
86
@Component
87
public class OrderServiceImpl implements OrderService {
88
 
89
	private static final Logger LOGGER = LoggerFactory.getLogger(OrderServiceImpl.class);
90
 
91
	@Autowired
92
	private InventoryItemRepository inventoryItemRepository;
93
 
94
	@Autowired
95
	private CurrentInventorySnapshotRepository currentInventorySnapshotRepository;
96
 
97
	@Autowired
98
	private InvoiceNumberGenerationSequenceRepository invoiceNumberGenerationSequenceRepository;
99
 
100
	@Autowired
101
	private CustomerRepository customerRepository;
102
 
103
	@Autowired
104
	private AddressRepository addressRepository;
105
 
106
	@Autowired
107
	private FofoLineItemRepository fofoLineItemRepository;
108
 
109
	@Autowired
110
	private FofoOrderItemRepository fofoOrderItemRepository;
111
 
112
	@Autowired
113
	private FofoOrderItemService fofoOrderItemService;
114
 
115
	@Autowired
116
	private PaymentOptionRepository paymentOptionRepository;
117
 
118
	@Autowired
119
	private ScanRecordRepository scanRecordRepository;
120
 
121
	@Autowired
122
	private FofoOrderRepository fofoOrderRepository;
123
 
124
	@Autowired
125
	private RetailerRepository retailerRepository;
126
 
127
	@Autowired
128
	private UserRepository userRepository;
129
 
130
	@Autowired
131
	private UserAccountRepository userAccountRepository;
132
 
133
	@Autowired
134
	private RetailerRegisteredAddressRepository retailerRegisteredAddressRepository;
135
 
136
	@Autowired
137
	private CustomerAddressRepository customerAddressRepository;
138
 
139
	@Autowired
140
	private ItemRepository itemRepository;
141
 
142
	@Autowired
143
	private InsuranceProviderRepository insuranceProviderRepository;
144
 
145
	@Autowired
146
	private InsurancePolicyRepository insurancePolicyRepository;
147
 
148
	@Autowired
149
	private PolicyNumberGenerationSequenceRepository policyNumberGenerationSequenceRepository;
150
 
151
	@Autowired
152
	private PricingService pricingService;
153
 
154
	@Autowired
155
	private PrivateDealUserRepository privateDealUserRepository;
156
 
157
	@Autowired
158
	private CounterRepository counterRepository;
159
 
160
	@Autowired
161
	private SchemeService schemeService;
162
 
163
	@Override
164
	public int createOrder(CreateOrderRequest createOrderRequest, int fofoId) throws ProfitMandiBusinessException {
165
 
166
		Set<Integer> itemIds = new HashSet<>();
167
		Map<Integer, Integer> itemIdQuantity = new HashMap<>(); //this is for error
168
		Map<Integer, List<CustomFofoOrderItem>> customFofoLineItemMap = new HashMap<>();
169
		Map<Integer, Float> lineItemPrice = new HashMap<>(); //this is for pricing error
170
 
171
		Map<Integer, Set<String>> itemIdSerialNumbers = new HashMap<>(); // 
172
 
173
		float totalAmount = 0;
174
		for(CustomFofoOrderItem customFofoOrderItem : createOrderRequest.getFofoOrderItems()){
175
			itemIds.add(customFofoOrderItem.getItemId());
176
			if(!customFofoOrderItem.getSerialNumberDetails().isEmpty() && customFofoOrderItem.getQuantity() != customFofoOrderItem.getSerialNumberDetails().size()){
177
				itemIdQuantity.put(customFofoOrderItem.getItemId(), customFofoOrderItem.getQuantity());
178
			}
179
			if(!(customFofoOrderItem.getSellingPrice() > 0)){
180
				lineItemPrice.put(customFofoOrderItem.getItemId(), customFofoOrderItem.getSellingPrice());
181
			}else{
182
				totalAmount = totalAmount + customFofoOrderItem.getSellingPrice() * customFofoOrderItem.getQuantity() - customFofoOrderItem.getDiscountAmount();
183
				for(SerialNumberDetail serialNumberDetail : customFofoOrderItem.getSerialNumberDetails()){
184
					if(serialNumberDetail.isInsurance() && serialNumberDetail.getAmount() > 0){
185
						totalAmount = totalAmount + serialNumberDetail.getAmount();
186
					}
187
				}
188
			}
189
 
190
			if(customFofoLineItemMap.containsKey(customFofoOrderItem.getItemId())) {
191
				customFofoLineItemMap.get(customFofoOrderItem.getItemId()).add(customFofoOrderItem);
192
			} else {
193
				List<CustomFofoOrderItem> customFofoLineItems = new ArrayList<>();
194
				customFofoLineItems.add(customFofoOrderItem);
195
				customFofoLineItemMap.put(customFofoOrderItem.getItemId(), customFofoLineItems);
196
			}
197
 
198
			Set<String> serialNumbers;
199
			if(!itemIdSerialNumbers.containsKey(customFofoOrderItem.getItemId())){
200
				serialNumbers = new HashSet<>();
201
			} else {
202
				serialNumbers = itemIdSerialNumbers.get(customFofoOrderItem.getItemId());
203
			}
204
			for(SerialNumberDetail serialNumberDetail : customFofoOrderItem.getSerialNumberDetails()){
205
				serialNumbers.add(serialNumberDetail.getSerialNumber());
206
			}
207
			itemIdSerialNumbers.put(customFofoOrderItem.getItemId(), serialNumbers);
208
		}
209
		if(!itemIdQuantity.isEmpty()){
210
			// if item quantity does not match with given serialnumbers size
211
			LOGGER.error("itemId's quantity should be equal to given serialnumber size {} ", itemIdQuantity);
212
			throw new ProfitMandiBusinessException("itemIdQuantity", itemIdQuantity, "");
213
			//return "error";
214
		}
215
 
216
		this.validatePaymentOptionsAndTotalAmount(createOrderRequest.getPaymentOptions(), totalAmount);
217
 
218
		if(!lineItemPrice.isEmpty()){
219
			// given fofo line item price must be greater than zero
220
			LOGGER.error("requested itemId's selling price must greater than 0");
221
			throw new ProfitMandiBusinessException(ProfitMandiConstants.PRICE, lineItemPrice, "");
222
		}
223
 
224
		List<CurrentInventorySnapshot> currentInventorySnapshots = currentInventorySnapshotRepository.selectByFofoItemIds(fofoId, itemIds);
225
 
226
		this.validateCurrentInventorySnapshotQuantities(itemIds.size(), currentInventorySnapshots, customFofoLineItemMap);
227
 
228
 
229
		List<Item> items = itemRepository.selectByIds(itemIds);
230
		Map<Integer, Item>  itemMap = this.toItemMap(items);
231
 
232
		Set<Integer> nonSerializedItemIds = new HashSet<>();
233
		Set<String> serialNumbers = new HashSet<>();
234
		Map<String, Float> insuranceSerialNumberItemPrice = new HashMap<>();
235
		Map<String, Float> insuranceSerialNumberSaleAmount = new HashMap<>();
236
		Map<String, String> serialNumberModelName = new HashMap<>();
237
		Map<String, String> serialNumberBrand = new HashMap<>();
238
		for (CustomFofoOrderItem cli : createOrderRequest.getFofoOrderItems()){
239
			Item item = itemMap.get(cli.getItemId());
240
			if (item.getType().equals(ItemType.SERIALIZED)){
241
				for (SerialNumberDetail serialNumberDetail : cli.getSerialNumberDetails()){
242
					serialNumbers.add(serialNumberDetail.getSerialNumber());
243
					if(serialNumberDetail.isInsurance()){
244
						insuranceSerialNumberItemPrice.put(serialNumberDetail.getSerialNumber(), cli.getSellingPrice());
245
						insuranceSerialNumberSaleAmount.put(serialNumberDetail.getSerialNumber(), serialNumberDetail.getAmount());
246
						serialNumberModelName.put(serialNumberDetail.getSerialNumber(), item.getModelName());
247
						serialNumberBrand.put(serialNumberDetail.getSerialNumber(), item.getBrand());
248
					}
249
				}
250
			}
251
			else{
252
				nonSerializedItemIds.add(cli.getItemId());
253
			}
254
		}
255
 
256
		Map<Integer, Set<InventoryItem>> serializedInventoryItemMap = new HashMap<>();
257
		Map<Integer, Set<InventoryItem>> nonSerializedInventoryItemMap = new HashMap<>();
258
		Map<Integer, List<Float>> itemIdPriceDropAmount = new HashMap<>();
259
		//Map<String, Float> serialNumberItemPrice = new HashMap<>();
260
 
261
		if (!serialNumbers.isEmpty()){
262
			List<InventoryItem> serializedInventoryItems = inventoryItemRepository.selectByFofoIdSerialNumbers(fofoId, serialNumbers);
263
			LOGGER.info("serializedInventoryItems {}", serializedInventoryItems);
264
			for (InventoryItem inventoryItem : serializedInventoryItems){
265
				if (inventoryItem.getGoodQuantity() == 1){
266
					if (serializedInventoryItemMap.containsKey(inventoryItem.getItemId())){
267
						serializedInventoryItemMap.get(inventoryItem.getItemId()).add(inventoryItem);
268
						itemIdPriceDropAmount.get(inventoryItem.getItemId()).
269
						add(inventoryItem.getUnitPrice() - (inventoryItem.getPriceDropAmount() == null ? 0 : inventoryItem.getPriceDropAmount()));
270
					}
271
					else{
272
						Set<InventoryItem> itemIdInventoryItems = new HashSet<>();
273
						itemIdInventoryItems.add(inventoryItem);
274
						serializedInventoryItemMap.put(inventoryItem.getItemId(), itemIdInventoryItems);
275
						ArrayList<Float> priceDropAmouts = new ArrayList<>();
276
						priceDropAmouts.add(inventoryItem.getUnitPrice() - (inventoryItem.getPriceDropAmount() == null ? 0 : inventoryItem.getPriceDropAmount()));
277
						itemIdPriceDropAmount.put(inventoryItem.getItemId(), priceDropAmouts);
278
					}
279
				}
280
			}
281
		}
282
 
283
		if (!nonSerializedItemIds.isEmpty()){
284
			List<InventoryItem> nonSerializedInventoryItems = inventoryItemRepository.selectByFofoIdItemIds(fofoId, nonSerializedItemIds);
285
			for (InventoryItem it : nonSerializedInventoryItems){
286
				if (it.getGoodQuantity() > 0){
287
					if (nonSerializedInventoryItemMap.containsKey(it.getItemId())){
288
						nonSerializedInventoryItemMap.get(it.getItemId()).add(it);
289
					}
290
					else{
291
						Set<InventoryItem> tmp = new HashSet<>();
292
						tmp.add(it);
293
						nonSerializedInventoryItemMap.put(it.getItemId(), tmp);
294
					}
295
				}
296
			}
297
		}
298
 
299
		this.validateItemsSerializedNonSerialized(items, customFofoLineItemMap);
300
 
301
		if(items.size() != itemIds.size()){
302
			LOGGER.error("Requested ItemIds not found in catalog");
303
			// invalid itemIds 
304
			throw new ProfitMandiBusinessException("invalidItemIds", "", "");
305
		}
306
 
307
		Map<Integer, Set<InventoryItem>> inventoryItemsToBill = new HashMap<>();
308
		Map<Integer, Integer> inventoryItemIdQuantityUsed = new HashMap<>(); //to keep track of inventoryitem quanity used for scan records insertion
309
 
310
		LOGGER.info("itemMap keys {}", itemMap.keySet());
311
		//Lets reduce quantity and decide what inventory items to use.
312
		for (Item item : items){
313
			if (item.getType().equals(ItemType.SERIALIZED)){
314
				//TODO:handle null
315
				/*if (serializedInventoryItemMap.get(item.getId()) == null || customFofoLineItemMap.get(item.getId()).size() != serializedInventoryItemMap.get(item.getId()).size()){
316
					LOGGER.info("serializedInventoryItemMap.get({}) == null || customFofoLineItemMap.get({}).size()[{}] != serializedInventoryItemMap.get({}).size()[{}]", item.getId(), item.getId(), customFofoLineItemMap.get(item.getId()).size(), item.getId(), serializedInventoryItemMap.get(item.getId()).size());
317
					//not enough serial numbers
318
					//LOGGER.info("serialNumbers {}", serialNumbers);
319
					LOGGER.info("serializedInventoryItemMap {}", serializedInventoryItemMap);
320
					LOGGER.info("itemId {}", item.getId());
321
					LOGGER.error("not enough serial numbers");
322
					throw new ProfitMandiBusinessException("notEnoughSerialNumbers", "", "");
323
				}*/
324
				Set<InventoryItem> inventoryItemsSerializedserialized = serializedInventoryItemMap.get(item.getId());
325
				for (InventoryItem it : inventoryItemsSerializedserialized){
326
					it.setGoodQuantity(0);
327
					inventoryItemIdQuantityUsed.put(it.getId(), 1);
328
				}
329
				inventoryItemsToBill.put(item.getId(), inventoryItemsSerializedserialized);
330
			}
331
			else{
332
				Set<InventoryItem> inventoryItemsNonSerialized = nonSerializedInventoryItemMap.get(item.getId());
333
				int quantityToBill = customFofoLineItemMap.get(item.getId()).get(0).getQuantity();
334
				int totalLeft = quantityToBill;
335
				Set<InventoryItem> inventoryItemsNonSerializedUsed = new HashSet<>();
336
				if (inventoryItemsNonSerialized!=null){
337
					for (InventoryItem inventoryItem : inventoryItemsNonSerialized){
338
						if (totalLeft > 0){
339
							int toUse = Math.min(totalLeft, inventoryItem.getGoodQuantity());
340
							inventoryItemIdQuantityUsed.put(inventoryItem.getId(), toUse);
341
							inventoryItem.setGoodQuantity(inventoryItem.getGoodQuantity()  - toUse);
342
							totalLeft = totalLeft - toUse;
343
							inventoryItemsNonSerializedUsed.add(inventoryItem);
344
						}
345
					}
346
				}
347
 
348
				if (totalLeft > 0){
349
					//not enough quanity for non-serialized
350
					LOGGER.error("not enough quanity for non-serialized");
351
					throw new ProfitMandiBusinessException("notEnoughQuantityForNonSerialized", "", "");
352
				}
353
				inventoryItemsToBill.put(item.getId(), inventoryItemsNonSerializedUsed);
354
			}
355
		}
356
 
357
		Map<Integer, PriceModel> itemIdMopPriceMap = pricingService.getPurchasePriceMopPriceNotFound(itemIds, fofoId);
358
 
359
		this.validateMopPrice(itemIdMopPriceMap, customFofoLineItemMap);
360
 
361
		InvoiceNumberGenerationSequence invoiceNumberGenerationSequence = this.createAndGetInvoiceNumberGenerationSequence(fofoId);
362
 
363
		CustomCustomer customCustomer = createOrderRequest.getCustomer();
364
 
365
		if(!StringUtils.isValidEmailAddress(customCustomer.getEmailId())){
366
			LOGGER.error("invalid customer emailId {} ", customCustomer.getEmailId());
367
			throw new ProfitMandiBusinessException(ProfitMandiConstants.EMAIL_ID, customCustomer.getEmailId(), "");
368
		}
369
 
370
		if(!StringUtils.isValidMobile(customCustomer.getMobileNumber())){
371
			LOGGER.error("invalid customer mobileNumber {} ", customCustomer.getMobileNumber());
372
			throw new ProfitMandiBusinessException(ProfitMandiConstants.MOBILE_NUMBER, customCustomer.getMobileNumber(), "");
373
		}
374
 
375
		boolean insurance = false;
376
		for(CustomFofoOrderItem customFofoOrderItem : createOrderRequest.getFofoOrderItems()){
377
			for(SerialNumberDetail serialNumberDetail : customFofoOrderItem.getSerialNumberDetails()){
378
				if(serialNumberDetail.getAmount() > 0){
379
					insurance = true;
380
					break;
381
				}
382
			}
383
		}
384
		LOGGER.info("insurance [{}] processing ....", insurance);
385
 
386
		Customer customer = this.createAndGetCustomer(customCustomer);
387
 
388
		CustomerAddress customerAddress = null;
389
		if(createOrderRequest.getCustomer().getCustomerAddressId() > 0){
390
			LOGGER.info("CustomerAddressId found [{}]", createOrderRequest.getCustomer().getCustomerAddressId());
391
			try{
392
				customerAddress = customerAddressRepository.selectById(createOrderRequest.getCustomer().getCustomerAddressId());
393
			}catch(ProfitMandiBusinessException profitMandiBusinessException){
394
				LOGGER.warn("Customer address not found with requested customerAddressId [{}]", createOrderRequest.getCustomer().getCustomerAddressId());
395
				customerAddress = this.createCustomerAddress(customCustomer.getAddress());
396
			}
397
		}else{
398
			LOGGER.info("CustomerAddressId not found");
399
			customerAddress = this.createCustomerAddress(customCustomer.getAddress());
400
		}
401
 
402
		customerAddress.setCustomerId(customer.getId());
403
		customerAddressRepository.persist(customerAddress);
404
 
405
		FofoOrder fofoOrder = this.createAndGetFofoOrder(customer.getId(), fofoId, invoiceNumberGenerationSequence, totalAmount, customerAddress.getId());
406
 
407
		this.createPaymentOptions(fofoOrder.getId(), createOrderRequest.getPaymentOptions());
408
 
409
		for(CustomFofoOrderItem customFofoOrderItem : createOrderRequest.getFofoOrderItems()){
410
			FofoOrderItem fofoOrderItem = this.createAndGetFofoOrderItem(customFofoOrderItem, fofoOrder.getId(), itemMap, inventoryItemsToBill.get(customFofoOrderItem.getItemId()), itemIdPriceDropAmount);
411
 
412
			Set<InventoryItem> inventoryItems = inventoryItemsToBill.get(customFofoOrderItem.getItemId());
413
 
414
			this.createFofoLineItem(fofoOrderItem.getId(), inventoryItems, inventoryItemIdQuantityUsed);
415
 
416
			this.updateCurrentInventorySnapshot(currentInventorySnapshots, fofoId, customFofoOrderItem.getItemId(), customFofoOrderItem.getQuantity());
417
 
418
			this.updateInventoryItemsAndScanRecord(inventoryItems, fofoId, inventoryItemIdQuantityUsed);
419
		}
420
 
421
		// insurance calculation is insurance flag is enabled
422
		if(!insuranceSerialNumberItemPrice.isEmpty()){
423
			LOGGER.info("Processing for insurence for serialNumbers");
424
			Map<Float, GadgetCopsInsuranceCalc> insurancePricesMap = pricingService.getInsurancePrices(new HashSet<>(insuranceSerialNumberItemPrice.values()), ProfitMandiConstants.GADGET_COPS);
425
			InsuranceProvider insuranceProvider = insuranceProviderRepository.selectByName(ProfitMandiConstants.GADGET_COPS);
426
 
427
			this.validateInsuranceAmount(insuranceSerialNumberItemPrice, insuranceSerialNumberSaleAmount, insurancePricesMap);
428
 
429
			this.validateInsuranceMargin(insuranceSerialNumberItemPrice, itemIdSerialNumbers, itemIdMopPriceMap, insurancePricesMap, insuranceSerialNumberSaleAmount);
430
 
431
			LocalDate customerDateOfBirth = this.validateCustomerDateOfBirth(createOrderRequest.getCustomerDateOfBirth());
432
 
433
			for(Map.Entry<String, Float> entry : insuranceSerialNumberItemPrice.entrySet()){
434
				PolicyNumberGenerationSequence policyNumberGenerationSequence = this.createPolicyNumberGenerationSequence();
435
 
436
				InsurancePolicy insurancePolicy = this.createInsurancePolicy(
437
						invoiceNumberGenerationSequence, fofoId,
438
						insurancePricesMap.get(entry.getValue()).getDealerPrice(),
439
						insuranceSerialNumberSaleAmount.get(entry.getKey()),entry.getValue(),
440
						entry.getKey(), serialNumberModelName.get(entry.getKey()),
441
						serialNumberBrand.get(entry.getKey()), policyNumberGenerationSequence.getSequence(),
442
						insuranceProvider.getId(), customer, customerDateOfBirth, customerAddress);
443
 
444
				GadgetCopsInsuranceModel gadgetCopsInsuranceModel = this.createGadgetCopsInsuranceModel(serialNumberBrand.get(entry.getKey()), serialNumberModelName.get(entry.getKey()), entry.getKey(), customerDateOfBirth, customer, customerAddress, insurancePolicy);
445
 
446
				try{
447
					InsuranceUtils.submitToGadgetCops(gadgetCopsInsuranceModel);
448
					insurancePolicy.setPosted(true);
449
				}catch (ProfitMandiBusinessException profitMandiBusinessException) {
450
					LOGGER.info("Unable to submit insurance policy details to {}", insuranceProvider.getName(), profitMandiBusinessException);
451
				}
452
				insurancePolicyRepository.persist(insurancePolicy);
453
			}
454
		}
455
		float cashback = schemeService.processSchemeOut(fofoOrder.getId(), fofoId);
456
		if(cashback > 0){
457
			fofoOrder.setCashback(cashback);
458
			fofoOrderRepository.persist(fofoOrder);
459
		}
460
		return fofoOrder.getId();
461
	}
462
 
463
	@Override
464
	public PdfModel getInvoicePdfModel(int fofoId, int orderId) throws ProfitMandiBusinessException {
465
 
466
		FofoOrder fofoOrder = fofoOrderRepository.selectByFofoIdAndOrderId(fofoId, orderId);
467
 
468
		PdfModel pdfModel = new PdfModel();
469
		pdfModel.setAuther("profitmandi");
470
		pdfModel.setTitle("Retailer Invoice");
471
		pdfModel.setInvoiceDate(fofoOrder.getFormattedDate());
472
 
473
		// insurance calculation
474
		List<InsurancePolicy> insurancePolicies = insurancePolicyRepository.selectByRetailerInvoiceNumber(fofoId, fofoOrder.getInvoiceNumber());
475
		Set<CustomInsurancePolicy> customInsurancePolicies = new HashSet<>();
476
		final float totalInsuranceTaxRate = 18;
477
		for(InsurancePolicy insurancePolicy : insurancePolicies){
478
			float taxableInsurancePrice = insurancePolicy.getSaleAmount() / (1 + totalInsuranceTaxRate / 100);
479
			CustomInsurancePolicy customInsurancePolicy = new CustomInsurancePolicy();
480
			customInsurancePolicy.setDescription("Damage Protection Plan for device IMEI #" + insurancePolicy.getSerialNumber() + "\n Certificate No. " + insurancePolicy.getPolicyNumber());
481
			customInsurancePolicy.setHsnCode("998716");
482
			customInsurancePolicy.setRate(taxableInsurancePrice);
483
			customInsurancePolicy.setIgstRate(18);
484
			customInsurancePolicy.setIgstAmount(taxableInsurancePrice * 18 /100);
485
			customInsurancePolicy.setCgstRate(18);
486
			customInsurancePolicy.setCgstAmount(taxableInsurancePrice * 9 /100);
487
			customInsurancePolicy.setSgstRate(9);
488
			customInsurancePolicy.setSgstAmount(taxableInsurancePrice * 9 /100);
489
			customInsurancePolicy.setNetAmount(insurancePolicy.getSaleAmount());
490
			customInsurancePolicies.add(customInsurancePolicy);
491
		}
492
		pdfModel.setInsurancePolicies(customInsurancePolicies);
493
		Customer customer = customerRepository.selectById(fofoOrder.getCustomerId());
494
		CustomCustomer customCustomer = new CustomCustomer();
495
		customCustomer.setFirstName(customer.getFirstName());
496
		customCustomer.setLastName(customer.getLastName());
497
		customCustomer.setEmailId(customer.getEmailId());
498
		customCustomer.setMobileNumber(customer.getMobileNumber());
499
		CustomerAddress customerAddress = customerAddressRepository.selectById(fofoOrder.getCustomerAddressId()); 
500
		customCustomer.setAddress(this.createCustomAddress(customerAddress));
501
		pdfModel.setCustomer(customCustomer);
502
		pdfModel.setInvoiceNumber(fofoOrder.getInvoiceNumber());
503
		pdfModel.setTotalAmount(fofoOrder.getTotalAmount());
504
 
505
		Retailer retailer = retailerRepository.selectById(fofoId);
506
		PrivateDealUser privateDealUser = null;
507
		try{
508
			privateDealUser = privateDealUserRepository.selectById(retailer.getId());
509
		}catch(ProfitMandiBusinessException profitMandiBusinessException){
510
			LOGGER.error("Private Deal User not found : ", profitMandiBusinessException);
511
		}
512
 
513
		User user = userRepository.selectById(userAccountRepository.selectUserIdByRetailerId(retailer.getId()));
514
		CustomRetailer customRetailer = new CustomRetailer();
515
		customRetailer.setBusinessName(retailer.getName());
516
		customRetailer.setMobileNumber(user.getMobileNumber());
517
		customRetailer.setTinNumber(retailer.getNumber());
518
		if(privateDealUser == null){
519
			customRetailer.setGstNumber(null);
520
		}else{
521
			if(null != privateDealUser.getCounterId()){
522
				Counter counter = counterRepository.selectById(privateDealUser.getCounterId());
523
				customRetailer.setGstNumber(counter.getGstin());
524
			}else{
525
				customRetailer.setGstNumber(null);
526
			}
527
		}
528
		Address retailerAddress = addressRepository.selectById(retailerRegisteredAddressRepository.selectAddressIdByRetailerId(retailer.getId()));
529
		customRetailer.setAddress(this.createCustomAddress(retailerAddress));
530
		pdfModel.setRetailer(customRetailer);
531
		List<FofoOrderItem> fofoOrderItems = fofoOrderItemService.getByOrderId(fofoOrder.getId());
532
 
533
		Set<CustomOrderItem> customerFofoOrderItems = new HashSet<>();
534
		for(FofoOrderItem fofoOrderItem : fofoOrderItems){
535
			CustomOrderItem customFofoOrderItem = new CustomOrderItem();
536
			float totalTaxRate = fofoOrderItem.getIgstRate() + fofoOrderItem.getSgstRate() + fofoOrderItem.getCgstRate();
537
			float taxableSellingPrice = fofoOrderItem.getSellingPrice() / (1 + totalTaxRate / 100);
538
			float taxableDiscountPrice = fofoOrderItem.getDiscount() / (1 + totalTaxRate / 100);
539
 
540
			customFofoOrderItem.setAmount(fofoOrderItem.getQuantity() * (taxableSellingPrice - taxableDiscountPrice));
541
			customFofoOrderItem.setDescription(fofoOrderItem.getBrand() + " " + fofoOrderItem.getModelName() + " " + fofoOrderItem.getModelNumber() + "-" + fofoOrderItem.getColor() + "\n IMEIS - " + String.join(", ",this.toSerialNumbers(fofoOrderItem.getFofoLineItems())));
542
			customFofoOrderItem.setRate(taxableSellingPrice);
543
			customFofoOrderItem.setDiscount(taxableDiscountPrice);
544
			customFofoOrderItem.setQuantity(fofoOrderItem.getQuantity());
545
			customFofoOrderItem.setNetAmount((fofoOrderItem.getSellingPrice()-fofoOrderItem.getDiscount())*fofoOrderItem.getQuantity());
546
			float igstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getIgstRate()) / 100;
547
			float cgstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getCgstRate()) / 100;
548
			float sgstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getSgstRate()) / 100;
549
			customFofoOrderItem.setIgstRate(fofoOrderItem.getIgstRate());
550
			customFofoOrderItem.setIgstAmount(igstAmount);
551
			customFofoOrderItem.setCgstRate(fofoOrderItem.getCgstRate());
552
			customFofoOrderItem.setCgstAmount(cgstAmount);
553
			customFofoOrderItem.setSgstRate(fofoOrderItem.getSgstRate());
554
			customFofoOrderItem.setSgstAmount(sgstAmount);
555
			customFofoOrderItem.setHsnCode(fofoOrderItem.getHsnCode());
556
			customerFofoOrderItems.add(customFofoOrderItem);
557
		}
558
		pdfModel.setOrderItems(customerFofoOrderItems);
559
		return pdfModel;
560
	}
561
 
562
	public String getBillingAddress(CustomerAddress customerAddress) {
563
		StringBuilder address = new StringBuilder();
564
		if ((customerAddress.getLine1() != null) && (!customerAddress.getLine1().isEmpty())) {
565
			address.append(customerAddress.getLine1());
566
			address.append(", ");
567
		}
568
 
569
		if ((customerAddress.getLine2() != null) && (!customerAddress.getLine2().isEmpty())) {
570
			address.append(customerAddress.getLine2());
571
			address.append(", ");
572
		}
573
 
574
		if ((customerAddress.getLandmark() != null) && (!customerAddress.getLandmark().isEmpty())) {
575
			address.append(customerAddress.getLandmark());
576
			address.append(", ");
577
		}
578
 
579
		if ((customerAddress.getCity() != null) && (!customerAddress.getCity().isEmpty())) {
580
			address.append(customerAddress.getCity());
581
			address.append(", ");
582
		}
583
 
584
		if ((customerAddress.getState() != null) && (!customerAddress.getState().isEmpty())) {
585
			address.append(customerAddress.getState());
586
		}
587
 
588
		if ((customerAddress.getPinCode() != null) && (!customerAddress.getPinCode().isEmpty())) {
589
			address.append("- ");
590
			address.append(customerAddress.getPinCode());
591
		}
592
 
593
		return address.toString();
594
	}
595
 
596
	@Override
597
	public List<CartFofo> cartCheckout(String cartJson) throws ProfitMandiBusinessException{
598
		try{
599
			JSONObject cartObject = new JSONObject(cartJson);
600
			Iterator<?> keys = cartObject.keys();
601
 
602
			Set<Integer> itemIds = new HashSet<>();
603
			List<CartFofo> cartItems = new ArrayList<CartFofo>();
604
 
605
			while( keys.hasNext() ) {
606
				String key = (String)keys.next();
607
				if ( cartObject.get(key) instanceof JSONObject ) {
608
					LOGGER.info(cartObject.get(key).toString());
609
				}
610
				CartFofo cf = new CartFofo();
611
				cf.setItemId(cartObject.getJSONObject(key).getInt("itemId"));
612
				cf.setQuantity(cartObject.getJSONObject(key).getInt("quantity"));
613
 
614
				if (cf.getQuantity() <= 0){
615
					continue;
616
				}
617
				cartItems.add(cf);
618
				itemIds.add(cartObject.getJSONObject(key).getInt("itemId"));
619
			}
620
			Map<Integer, Item>  itemMap = new HashMap<Integer, Item>();
621
			if (itemIds.size() > 0){
622
				List<Item> items = itemRepository.selectByIds(itemIds);
623
				for (Item i : items){
624
					itemMap.put(i.getId(), i);
625
				}
626
 
627
			}
628
			for (CartFofo cf : cartItems){
629
				Item i = itemMap.get(cf.getItemId());
630
				if (i == null){
631
					continue;
632
				}
633
				cf.setDisplayName(getValidName(i.getBrand())+" "+getValidName(i.getModelName())+" "+getValidName(i.getModelNumber())+" "+getValidName(i.getColor()).replaceAll("\\s+", " "));
634
				cf.setItemType(i.getType());
635
			}
636
			return cartItems;
637
		}catch (Exception e) {
638
			LOGGER.error("Unable to Prepare cart to place order...", e);
639
			throw new ProfitMandiBusinessException("cartData", cartJson, "");
640
		}
641
	}
642
 
643
	private String getValidName(String name){
644
		return name!=null?name:"";
645
	}
646
 
647
	private Set<String> toSerialNumbers(Set<FofoLineItem> fofoLineItems){
648
		Set<String> serialNumbers = new HashSet<>();
649
		for(FofoLineItem fofoLineItem : fofoLineItems){
650
			serialNumbers.add(fofoLineItem.getSerialNumber());
651
		}
652
		return serialNumbers;	
653
	}
654
 
655
 
656
	private PolicyNumberGenerationSequence createPolicyNumberGenerationSequence(){
657
		PolicyNumberGenerationSequence policyNumberGenerationSequence = null;
658
		try{
659
			policyNumberGenerationSequence = policyNumberGenerationSequenceRepository.select();
660
			policyNumberGenerationSequence.setSequence(policyNumberGenerationSequence.getSequence() + 1);
661
			policyNumberGenerationSequenceRepository.persist(policyNumberGenerationSequence);
662
		}catch(ProfitMandiBusinessException profitMandiBusinessException){
663
			policyNumberGenerationSequence = new PolicyNumberGenerationSequence();
664
			policyNumberGenerationSequence.setSequence(1);
665
			policyNumberGenerationSequenceRepository.persist(policyNumberGenerationSequence);
666
		}
667
		return policyNumberGenerationSequence;
668
	}
669
 
670
	private GadgetCopsInsuranceModel createGadgetCopsInsuranceModel(String brand, String modelName, String serialNumber, LocalDate customerDateOfBirth, Customer customer, CustomerAddress customerAddress, InsurancePolicy insurancePolicy){
671
		GadgetCopsInsuranceModel gadgetCopsInsuranceModel = new GadgetCopsInsuranceModel();
672
		gadgetCopsInsuranceModel.setBrand(brand);
673
		gadgetCopsInsuranceModel.setModelName(modelName);
674
		gadgetCopsInsuranceModel.setSerialNumber(serialNumber);
675
		gadgetCopsInsuranceModel.setCustomerFirstName(customer.getFirstName());
676
		gadgetCopsInsuranceModel.setCustomerLastName(customer.getLastName());
677
		gadgetCopsInsuranceModel.setCustomerDateOfBirth(customerDateOfBirth);
678
		gadgetCopsInsuranceModel.setCustomerMobileNumber(customer.getMobileNumber());
679
		gadgetCopsInsuranceModel.setCustomerEmailId(customer.getEmailId());
680
		gadgetCopsInsuranceModel.setCustomerAddress1(customerAddress.getLine1());
681
		gadgetCopsInsuranceModel.setCustomerAddress2(customerAddress.getLine2());
682
		gadgetCopsInsuranceModel.setCustomerCity(customerAddress.getCity());
683
		gadgetCopsInsuranceModel.setCustomerPinCode(customerAddress.getPinCode());
684
		gadgetCopsInsuranceModel.setCustomerState(customerAddress.getState());
685
		gadgetCopsInsuranceModel.setPrice(insurancePolicy.getSellingPrice());
686
		gadgetCopsInsuranceModel.setInvoiceNumber(insurancePolicy.getInvoiceNumber());
687
		gadgetCopsInsuranceModel.setPolicyNumber(insurancePolicy.getPolicyNumber());
688
		return gadgetCopsInsuranceModel;
689
	}
690
 
691
	private InsurancePolicy createInsurancePolicy(InvoiceNumberGenerationSequence invoiceNumberGenerationSequence, int retailerId, float purchaseAmount, float saleAmount, float sellingPrice, String serialNumber, String modelName, String brand, int policyNumberGenerationSequence, int insuranceProviderId, Customer customer, LocalDate customerDateOfBirth, CustomerAddress customerAddress){
692
		InsurancePolicy insurancePolicy = new InsurancePolicy();
693
		insurancePolicy.setInvoiceNumber(invoiceNumberGenerationSequence.getPrefix() + invoiceNumberGenerationSequence.getSequence());
694
		insurancePolicy.setRetailerId(retailerId);
695
		insurancePolicy.setPurchaseAmount(purchaseAmount);
696
		insurancePolicy.setSaleAmount(saleAmount);
697
		insurancePolicy.setSellingPrice(sellingPrice);
698
		insurancePolicy.setSerialNumber(serialNumber);
699
		insurancePolicy.setModelName(modelName);
700
		insurancePolicy.setBrand(brand);
701
		insurancePolicy.setPolicyNumber(StringUtils.generatePolicyNumber(ProfitMandiConstants.POLICY_NUMBER_PREFIX, policyNumberGenerationSequence));
702
		insurancePolicy.setProviderId(insuranceProviderId);
703
		insurancePolicy.setCustomerFirstName(customer.getFirstName());
704
		insurancePolicy.setCustomerLastName(customer.getLastName());
705
		insurancePolicy.setCustomerMobileNumber(customer.getMobileNumber());
706
		insurancePolicy.setCustomerEmailId(customer.getEmailId());
707
		insurancePolicy.setCustomerDateOfBirth(customerDateOfBirth);
708
		insurancePolicy.setCustomerAddress1(customerAddress.getLine1());
709
		insurancePolicy.setCustomerAddress2(customerAddress.getLine2());
710
		insurancePolicy.setCustomerCity(customerAddress.getCity());
711
		insurancePolicy.setCustomerPinCode(customerAddress.getPinCode());
712
		insurancePolicy.setCustomerState(customerAddress.getState());
713
		return insurancePolicy;
714
	}
715
 
716
	private void validateInsuranceMargin(Map<String, Float> insuranceSerialNumberItemPrice, Map<Integer, Set<String>> itemIdSerialNumbers, Map<Integer, PriceModel> itemIdMopPriceMap, Map<Float, GadgetCopsInsuranceCalc> insurancePricesMap, Map<String, Float> insuranceSerialNumberSaleAmount) throws ProfitMandiBusinessException{
717
		Map<Float, Float> invalidInsuranceMarginAmount = new HashMap<>();
718
		for(Map.Entry<String, Float> entry : insuranceSerialNumberItemPrice.entrySet()){
719
			int itemId = this.getItemIdFromSerialNumber(itemIdSerialNumbers, entry.getKey());
720
			float itemPurchasePrice = itemIdMopPriceMap.get(itemId).getPrice();
721
			float itemSellingPrice = entry.getValue();
722
			float itemMargin = itemSellingPrice - itemPurchasePrice;
723
			float insurancePurchasePrice = insurancePricesMap.get(entry.getValue()).getDealerPrice();
724
			float insuranceSellingPrice = insuranceSerialNumberSaleAmount.get(entry.getKey());
725
			float insuranceMargin = insuranceSellingPrice - insurancePurchasePrice;
726
			if(insuranceMargin < (itemMargin * 30 / 100)){
727
				invalidInsuranceMarginAmount.put(insuranceMargin, (itemMargin * 30 / 100));
728
			}
729
		}
730
		if(!invalidInsuranceMarginAmount.isEmpty()){
731
			LOGGER.error("insurance marging should be greater than equal to item profit margin insuranceMarginItemIdMargin {}", invalidInsuranceMarginAmount);
732
			throw new ProfitMandiBusinessException("invalidInsuranceMarginAmount", invalidInsuranceMarginAmount, "");
733
		}
734
	}
735
 
736
	private void validateInsuranceAmount(Map<String, Float> insuranceSerialNumberItemPrice, Map<String, Float> insuranceSerialNumberSaleAmount, Map<Float, GadgetCopsInsuranceCalc> insurancePricesMap) throws ProfitMandiBusinessException{
737
		Map<Float, Float> invalidInsurancePurchaseSaleAmount = new HashMap<>();
738
		Map<Float, Float> invalidInsuranceSalePurchaseAmount = new HashMap<>();
739
		for(Map.Entry<String, Float> entry : insuranceSerialNumberItemPrice.entrySet()){
740
			if(insuranceSerialNumberSaleAmount.get(entry.getKey()) < insurancePricesMap.get(entry.getValue()).getDealerPrice()){
741
				invalidInsurancePurchaseSaleAmount.put(insurancePricesMap.get(entry.getValue()).getDealerPrice(), insuranceSerialNumberSaleAmount.get(entry.getKey()));
742
			}
743
 
744
			if(insuranceSerialNumberSaleAmount.get(entry.getKey()) > insurancePricesMap.get(entry.getValue()).getSellingPrice()){
745
				invalidInsuranceSalePurchaseAmount.put(insuranceSerialNumberSaleAmount.get(entry.getKey()), insurancePricesMap.get(entry.getValue()).getDealerPrice());
746
			}
747
		}
748
 
749
		// insurance sale amount can not be lesser than insurance purchase amount
750
		if(!invalidInsurancePurchaseSaleAmount.isEmpty()){
751
			LOGGER.error("Invalid Insurance prices [{}], insurance sale amount can not be lesser than insurance purchase amount", invalidInsurancePurchaseSaleAmount);
752
			throw new ProfitMandiBusinessException("invalidInsurancePurchaseSaleAmount", invalidInsurancePurchaseSaleAmount, "");
753
		}
754
 
755
		if(!invalidInsuranceSalePurchaseAmount.isEmpty()){
756
			LOGGER.error("Invalid Insurance prices [{}], insurance sale amount can not be greater than than insurance max amount", invalidInsuranceSalePurchaseAmount);
757
			throw new ProfitMandiBusinessException("invalidInsuranceSalePurchaseAmount", invalidInsuranceSalePurchaseAmount, "");
758
		}
759
	}
760
 
761
	private void validateMopPrice(Map<Integer, PriceModel> itemIdMopPriceMap, Map<Integer, List<CustomFofoOrderItem>> customFofoLineItemMap) throws ProfitMandiBusinessException{
762
		Map<Integer, Float> invalidMopItemIdPriceMap = new HashMap<>();
763
		Map<Integer, Float> invalidDiscountAmountMap = new HashMap<>();
764
		//Map<Integer, PriceModel> itemIdMopPriceMap = pricingService.getPurchasePriceMopPriceNotFound(itemIds, fofoId);
765
		for(Map.Entry<Integer, PriceModel> entry : itemIdMopPriceMap.entrySet()){
766
			List<CustomFofoOrderItem>customFofoLineItems = customFofoLineItemMap.get(entry.getKey());
767
			for(CustomFofoOrderItem customFofoOrderItem : customFofoLineItems) {
768
				if(entry.getValue().getPrice() < Float.MAX_VALUE && customFofoOrderItem.getSellingPrice() < entry.getValue().getPrice()){
769
					invalidMopItemIdPriceMap.put(entry.getKey(), customFofoOrderItem.getSellingPrice());
770
				}
771
				if(entry.getValue().isMop() && customFofoOrderItem.getDiscountAmount() > entry.getValue().getMaxDiscountAmount()){
772
					invalidDiscountAmountMap.put(entry.getKey(), customFofoOrderItem.getDiscountAmount());
773
				}
774
			}
775
		}
776
 
777
		if(!invalidMopItemIdPriceMap.isEmpty()){
778
			LOGGER.error("Invalid itemIds selling prices{} should be greater than mop prices {}", invalidMopItemIdPriceMap, itemIdMopPriceMap);
779
			throw new ProfitMandiBusinessException("invalidMopItemIdPrice", invalidMopItemIdPriceMap, "");
780
		}
781
 
782
		if(!invalidMopItemIdPriceMap.isEmpty()){
783
			LOGGER.error("Invalid itemIds discount amounts {} should be less than maxDiscount prices {}", invalidDiscountAmountMap, itemIdMopPriceMap);
784
			throw new ProfitMandiBusinessException("invalidMopItemIdPrice", invalidDiscountAmountMap, "");
785
		}
786
	}
787
 
788
	private LocalDate validateCustomerDateOfBirth(String customerDateOfBirthString) throws ProfitMandiBusinessException{
789
		LocalDate customerDateOfBirth = null;
790
		try{
791
			customerDateOfBirth = StringUtils.toDate(customerDateOfBirthString);
792
		}catch(DateTimeException dateTimeException){
793
			LOGGER.error("Unable to parse dateOfBirth", dateTimeException);
794
			throw new ProfitMandiBusinessException("dateOfBirth", customerDateOfBirthString, "");
795
		}
796
		return customerDateOfBirth;
797
	}
798
 
799
	private void updateInventoryItemsAndScanRecord(Set<InventoryItem> inventoryItems, int fofoId, Map<Integer, Integer> inventoryItemQuantityUsed){
800
		for(InventoryItem inventoryItem : inventoryItems){
801
			inventoryItem.setLastScanType(ScanType.SALE);
802
			inventoryItemRepository.persist(inventoryItem);
803
			ScanRecord scanRecord = new ScanRecord();
804
			scanRecord.setInventoryItemId(inventoryItem.getId());
805
			scanRecord.setFofoId(fofoId);
806
			//correct this
807
			scanRecord.setQuantity(inventoryItemQuantityUsed.get(inventoryItem.getId()));
808
			scanRecord.setType(ScanType.SALE);
809
			scanRecordRepository.persist(scanRecord);
810
		}
811
	}
812
 
813
	private void createFofoLineItem(int fofoOrderItemId, Set<InventoryItem> inventoryItems, Map<Integer, Integer> inventoryItemIdQuantityUsed){
814
		for(InventoryItem inventoryItem : inventoryItems){
815
			FofoLineItem fofoLineItem = new FofoLineItem();
816
			fofoLineItem.setFofoOrderItemId(fofoOrderItemId);
817
			fofoLineItem.setSerialNumber(inventoryItem.getSerialNumber());
818
			fofoLineItem.setInventoryItemId(inventoryItem.getId());
819
			fofoLineItem.setQuantity(inventoryItemIdQuantityUsed.get(inventoryItem.getId()));
820
			fofoLineItemRepository.persist(fofoLineItem);
821
		}
822
	}
823
 
824
	private FofoOrderItem createAndGetFofoOrderItem(CustomFofoOrderItem customFofoOrderItem, int fofoOrderId, Map<Integer, Item> itemMap, Set<InventoryItem> inventoryItems, Map<Integer, List<Float>> itemIdPriceDropAmount){
825
		FofoOrderItem fofoOrderItem = new FofoOrderItem();
826
		fofoOrderItem.setItemId(customFofoOrderItem.getItemId());
827
		fofoOrderItem.setQuantity(customFofoOrderItem.getQuantity());
828
		fofoOrderItem.setSellingPrice(customFofoOrderItem.getSellingPrice());
829
		fofoOrderItem.setOrderId(fofoOrderId);
830
		fofoOrderItem.setDp(customFofoOrderItem.getSellingPrice());
831
		fofoOrderItem.setDiscount(customFofoOrderItem.getDiscountAmount());
832
		Item item = itemMap.get(customFofoOrderItem.getItemId());
833
		for(InventoryItem inventoryItem : inventoryItems){
834
			fofoOrderItem.setIgstRate(inventoryItem.getIgstRate());
835
			fofoOrderItem.setCgstRate(inventoryItem.getCgstRate());
836
			fofoOrderItem.setSgstRate(inventoryItem.getSgstRate());
837
			fofoOrderItem.setHsnCode(inventoryItem.getHsnCode());
838
			break;
839
		}
840
		List<Float> priceDropAmounts = itemIdPriceDropAmount.get(customFofoOrderItem.getItemId());
841
		float cost = 0;
842
		if (priceDropAmounts!=null){
843
			for (Float pda : priceDropAmounts){
844
				cost = cost + pda;
845
			}
846
		}
847
		else{
848
			cost = customFofoOrderItem.getSellingPrice() * customFofoOrderItem.getQuantity();
849
		}
850
		fofoOrderItem.setCost(cost);
851
		fofoOrderItem.setBrand(item.getBrand());
852
		fofoOrderItem.setModelName(item.getModelName());
853
		fofoOrderItem.setModelNumber(item.getModelNumber());
854
		fofoOrderItem.setColor(item.getColor());
855
		fofoOrderItemRepository.persist(fofoOrderItem);
856
		return fofoOrderItem;
857
	}
858
 
859
	private void updateCurrentInventorySnapshot(List<CurrentInventorySnapshot> currentInventorySnapshots, int fofoId, int itemId, int quantity) throws ProfitMandiBusinessException{
860
		for(CurrentInventorySnapshot currentInventorySnapshot : currentInventorySnapshots){
861
			if(currentInventorySnapshot.getItemId() == itemId && currentInventorySnapshot.getFofoId() == fofoId){
862
				currentInventorySnapshotRepository.updateAvailabilityByItemIdAndFofoId(itemId, fofoId, currentInventorySnapshot.getAvailability() - quantity);
863
			}
864
		}
865
	}
866
 
867
	private void createPaymentOptions(int fofoOrderId, Set<CustomPaymentOption> customPaymentOptions){
868
		for(CustomPaymentOption customPaymentOption : customPaymentOptions){
869
			if(customPaymentOption.getAmount() > 0){
870
				PaymentOption paymentOption = new PaymentOption();
871
				paymentOption.setOrderId(fofoOrderId);
872
				paymentOption.setAmount(customPaymentOption.getAmount());
873
				paymentOption.setType(PaymentOptionType.valueOf(customPaymentOption.getType()));
874
				paymentOptionRepository.persist(paymentOption);
875
			}
876
		}
877
	}
878
 
879
	private FofoOrder createAndGetFofoOrder(int customerId, int fofoId, InvoiceNumberGenerationSequence invoiceNumberGenerationSequence, float totalAmount, int customerAddressId){
880
		FofoOrder fofoOrder = new FofoOrder();
881
		fofoOrder.setCustomerId(customerId);
882
		fofoOrder.setFofoId(fofoId);
883
		fofoOrder.setInvoiceNumber(invoiceNumberGenerationSequence.getPrefix() + invoiceNumberGenerationSequence.getSequence());
884
		fofoOrder.setTotalAmount(totalAmount);
885
		fofoOrder.setCustomerAddressId(customerAddressId);
886
		fofoOrderRepository.persist(fofoOrder);
887
		return fofoOrder;
888
	}
889
 
890
	private Customer createAndGetCustomer(CustomCustomer customCustomer) throws ProfitMandiBusinessException{
891
		Customer customer = null;
892
		try{
893
			customer = customerRepository.selectByMobileNumber(customCustomer.getMobileNumber());
894
		}catch(ProfitMandiBusinessException profitMandiBusinessException){
895
			LOGGER.error("Error : ", profitMandiBusinessException);
896
			customer = new Customer();
897
			customer.setFirstName(customCustomer.getFirstName());
898
			customer.setLastName(customCustomer.getLastName());
899
			customer.setEmailId(customCustomer.getEmailId());
900
			customer.setMobileNumber(customCustomer.getMobileNumber());
901
			customerRepository.persist(customer);
902
		}
903
		return customer;
904
	}
905
 
906
	private InvoiceNumberGenerationSequence createAndGetInvoiceNumberGenerationSequence(int fofoId){
907
		InvoiceNumberGenerationSequence invoiceNumberGenerationSequence = null;
908
		try{
909
			invoiceNumberGenerationSequence = invoiceNumberGenerationSequenceRepository.selectByFofoId(fofoId);
910
			invoiceNumberGenerationSequence.setSequence(invoiceNumberGenerationSequence.getSequence() + 1);
911
		}catch(ProfitMandiBusinessException profitMandiBusinessException){
912
			invoiceNumberGenerationSequence = new InvoiceNumberGenerationSequence();
913
			invoiceNumberGenerationSequence.setFofoId(fofoId);
914
			invoiceNumberGenerationSequence.setPrefix("INVOICE");
915
			invoiceNumberGenerationSequence.setSequence(1);
916
		}
917
		invoiceNumberGenerationSequenceRepository.persist(invoiceNumberGenerationSequence);
918
		return invoiceNumberGenerationSequence;
919
	}
920
 
921
	private void validateItemsSerializedNonSerialized(List<Item> items, Map<Integer, List<CustomFofoOrderItem>> customFofoLineItemMap) throws ProfitMandiBusinessException{
922
 		List<Integer> invalidItemIdSerialNumbers = new ArrayList<Integer>();
923
		List<Integer> itemIdNonSerializedSerialNumbers = new ArrayList<Integer>();
924
		for (Item i : items){
925
			List<CustomFofoOrderItem> customFofoLineItems = customFofoLineItemMap.get(i.getId());
926
			for(CustomFofoOrderItem customFofoOrderItem: customFofoLineItems) {
927
				if (i.getType().equals(ItemType.SERIALIZED)){
928
					if (customFofoOrderItem ==null || customFofoOrderItem.getSerialNumberDetails().isEmpty()){
929
						invalidItemIdSerialNumbers.add(i.getId());
930
					}
931
				}
932
				else{
933
					if (customFofoOrderItem == null || !customFofoOrderItem.getSerialNumberDetails().isEmpty()){
934
						itemIdNonSerializedSerialNumbers.add(i.getId());
935
					}
936
				}
937
			}
938
		}
939
 
940
		if(!invalidItemIdSerialNumbers.isEmpty()){
941
			LOGGER.error("Invalid itemId's serialNumbers for serialized{}", invalidItemIdSerialNumbers);
942
			// itemId's are serialized you are saying these are not serialized
943
			throw new ProfitMandiBusinessException("invalidItemIdSerialNumbers", invalidItemIdSerialNumbers, "");
944
		}
945
 
946
		if(!itemIdNonSerializedSerialNumbers.isEmpty()){
947
			LOGGER.error("Invalid itemId's serialNumbers for non serialized{}", itemIdNonSerializedSerialNumbers);
948
			// itemId's are non serialized you are saying these are serialized
949
			throw new ProfitMandiBusinessException("itemIdNonSerializedSerialNumbers", itemIdNonSerializedSerialNumbers, "");
950
		}
951
	}
952
 
953
	private void validateCurrentInventorySnapshotQuantities(int actualSize, List<CurrentInventorySnapshot> currentInventorySnapshots, Map<Integer, List<CustomFofoOrderItem>> customFofoLineItemMap) throws ProfitMandiBusinessException{
954
		if(actualSize != currentInventorySnapshots.size()){
955
			throw new ProfitMandiBusinessException("quantiiesSize", currentInventorySnapshots.size(), "");
956
		}
957
		List<ItemIdQuantityAvailability> itemIdQuantityAvailabilities = new ArrayList<>(); //this is for error
958
		LOGGER.info("currentInventorySnapshots "+currentInventorySnapshots);
959
		LOGGER.info("CustomFofoLineItemMap {}", customFofoLineItemMap);
960
		for(CurrentInventorySnapshot currentInventorySnapshot : currentInventorySnapshots){
961
			List<CustomFofoOrderItem> customFofoLineItems = customFofoLineItemMap.get(currentInventorySnapshot.getItemId());
962
			LOGGER.info("customFofoLineItems {}", customFofoLineItems);
963
			for (CustomFofoOrderItem customFofoOrderItem : customFofoLineItems) {
964
				if(customFofoOrderItem.getQuantity() > currentInventorySnapshot.getAvailability()){
965
					ItemIdQuantityAvailability itemIdQuantityAvailability = new ItemIdQuantityAvailability();
966
					itemIdQuantityAvailability.setItemId(customFofoOrderItem.getItemId());
967
					Quantity quantity = new Quantity();
968
					quantity.setAvailable(currentInventorySnapshot.getAvailability());
969
					quantity.setRequested(customFofoOrderItem.getQuantity());
970
					itemIdQuantityAvailability.setQuantity(quantity);
971
					itemIdQuantityAvailabilities.add(itemIdQuantityAvailability);
972
				}
973
			}
974
 
975
		}
976
 
977
 
978
 
979
		if(!itemIdQuantityAvailabilities.isEmpty()){
980
			// itemIdQuantity request is not valid
981
			LOGGER.error("Requested quantities should not be greater than currently available quantities {}", itemIdQuantityAvailabilities);
982
			throw new ProfitMandiBusinessException("itemIdQuantityAvailabilities", itemIdQuantityAvailabilities, "");
983
		}
984
	}
985
 
986
	private int getItemIdFromSerialNumber(Map<Integer, Set<String>> itemIdSerialNumbers, String serialNumber){
987
		for(Map.Entry<Integer, Set<String>> entry : itemIdSerialNumbers.entrySet()){
988
			if(entry.getValue().contains(serialNumber)){
989
				return entry.getKey();
990
			}
991
		}
992
		return 0;
993
	}
994
 
995
	private Map<Integer, Item> toItemMap(List<Item> items){
996
		Map<Integer, Item>  itemMap = new HashMap<Integer, Item>();
997
		for (Item i : items){
998
			itemMap.put(i.getId(), i);
999
		}
1000
		return itemMap;
1001
	}
1002
 
1003
	private CustomerAddress createCustomerAddress(CustomAddress customAddress){
1004
		CustomerAddress customerAddress = new CustomerAddress();
1005
		customerAddress.setName(customAddress.getName());
1006
		customerAddress.setLine1(customAddress.getLine1());
1007
		customerAddress.setLine2(customAddress.getLine2());
1008
		customerAddress.setLandmark(customAddress.getLandmark());
1009
		customerAddress.setCity(customAddress.getCity());
1010
		customerAddress.setPinCode(customAddress.getPinCode());
1011
		customerAddress.setState(customAddress.getState());
1012
		customerAddress.setCountry(customAddress.getCountry());
1013
		customerAddress.setPhoneNumber(customAddress.getPhoneNumber());
1014
		return customerAddress;
1015
	}
1016
 
1017
	private CustomAddress createCustomAddress(Address address){
1018
		CustomAddress customAddress = new CustomAddress();
1019
		customAddress.setName(address.getName());
1020
		customAddress.setLine1(address.getLine1());
1021
		customAddress.setLine2(address.getLine2());
1022
		customAddress.setLandmark(address.getLandmark());
1023
		customAddress.setCity(address.getCity());
1024
		customAddress.setPinCode(address.getPinCode());
1025
		customAddress.setState(address.getState());
1026
		customAddress.setCountry(address.getCountry());
1027
		customAddress.setPhoneNumber(address.getPhoneNumber());
1028
		return customAddress;
1029
	}
1030
 
1031
	private CustomAddress createCustomAddress(CustomerAddress customerAddress){
1032
		CustomAddress customAddress = new CustomAddress();
1033
		customAddress.setName(customerAddress.getName());
1034
		customAddress.setLine1(customerAddress.getLine1());
1035
		customAddress.setLine2(customerAddress.getLine2());
1036
		customAddress.setLandmark(customerAddress.getLandmark());
1037
		customAddress.setCity(customerAddress.getCity());
1038
		customAddress.setPinCode(customerAddress.getPinCode());
1039
		customAddress.setState(customerAddress.getState());
1040
		customAddress.setCountry(customerAddress.getCountry());
1041
		customAddress.setPhoneNumber(customerAddress.getPhoneNumber());
1042
		return customAddress;
1043
	}
1044
 
1045
	private void validatePaymentOptionsAndTotalAmount(Set<CustomPaymentOption> customPaymentOptions, float totalAmount) throws ProfitMandiBusinessException
1046
	{
1047
		float calculatedAmount = 0;
1048
		Set<String> paymentOptionTypes = new HashSet<>();
1049
		for(CustomPaymentOption customPaymentOption : customPaymentOptions){
1050
			if(paymentOptionTypes.contains(PaymentOptionType.valueOf(customPaymentOption.getType()))){
1051
				throw new ProfitMandiBusinessException(ProfitMandiConstants.PAYMENT_OPTION_TYPE, customPaymentOption.getType(), "");
1052
			}else{
1053
				paymentOptionTypes.add(customPaymentOption.getType());
1054
				calculatedAmount = calculatedAmount + customPaymentOption.getAmount();
1055
			}
1056
		}
1057
		if(calculatedAmount != totalAmount){
1058
			LOGGER.error("Error occured while validating payment options amount[{}] != TotalAmount [{}]", calculatedAmount, totalAmount);
1059
			throw new ProfitMandiBusinessException(ProfitMandiConstants.PAYMENT_OPTION_CALCULATED_AMOUNT, calculatedAmount, "");
1060
		}
1061
	}
1062
 
1063
}