package com.ssbusy.core.myorder.service;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.broadleafcommerce.common.money.Money;
import org.broadleafcommerce.core.catalog.domain.Sku;
import org.broadleafcommerce.core.order.domain.LocationedItem;
import org.broadleafcommerce.core.order.domain.Order;
import org.broadleafcommerce.core.order.domain.OrderItem;
import org.broadleafcommerce.core.order.domain.SkuAccessor;
import org.broadleafcommerce.core.order.service.OrderServiceImpl;
import org.broadleafcommerce.core.order.service.call.OrderItemRequestDTO;
import org.broadleafcommerce.core.order.service.exception.AddToCartException;
import org.broadleafcommerce.core.order.service.exception.RemoveFromCartException;
import org.broadleafcommerce.core.order.service.exception.UpdateCartException;
import org.broadleafcommerce.core.order.service.type.OrderStatus;
import org.broadleafcommerce.core.payment.domain.PaymentInfo;
import org.broadleafcommerce.core.pricing.service.exception.PricingException;
import org.broadleafcommerce.inventory.domain.FulfillmentLocation;
import org.broadleafcommerce.inventory.exception.ConcurrentInventoryModificationException;
import org.broadleafcommerce.inventory.service.InventoryService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ssbusy.core.account.domain.MyCustomer;
import com.ssbusy.core.account.service.BalanceChangeType;
import com.ssbusy.core.account.service.MyCustomerService;
import com.ssbusy.core.myorder.dao.MyOrderDao;
import com.ssbusy.core.myorder.domain.MyOrder;
import com.ssbusy.payment.service.type.MyPaymentInfoType;
@Service("ssbMyOrderService")
public class MyOrderServiceImpl extends OrderServiceImpl implements
MyOrderService {
private static final Log LOG = LogFactory.getLog(MyOrderServiceImpl.class);
@Resource(name = "ssbMyOrderDao")
protected MyOrderDao myOrderDao;
@Resource(name = "blInventoryService")
protected InventoryService inventoryService;
@Resource(name = "blCustomerService")
protected MyCustomerService myCustomerService;
@Override
public List<Order> findOrdersForProcess() {
return myOrderDao.findOrderForProcess();
}
@Transactional("blTransactionManager")
public void processOrderStatus(Long[] orderIds, OrderStatus status) {
myOrderDao.setOrderStatus(orderIds, status);
}
@Override
public Long countOrderByTime(Date lastTime,
FulfillmentLocation fulfillmentLocation) {
return myOrderDao.countOrderByTime(lastTime, fulfillmentLocation);
}
@Override
public Order loadOrderByOrderId(long orderId) {
return myOrderDao.loadOrderByOrderId(orderId);
}
@Override
public List<Order> getOrderListByOrderIdsAndAdminUserId(Long[] orderIds,
Long adminUserId) {
return myOrderDao.getOrderListByOrderIds(orderIds, adminUserId);
}
@Override
public List<MyOrder> getOrderListByStatus(OrderStatus status,
Long fulfillmentLocationId) {
return myOrderDao.getOrderListByStatus(status, fulfillmentLocationId);
}
@Transactional("blTransactionManager")
public void setOrderUpdateBy(Long[] orderIds, Long adminUserId) {
myOrderDao.setOrderUpdateBy(orderIds, adminUserId);
}
public List<Order> getOrderListByStatusAndAdminUserId(OrderStatus status,
Long adminUserId) {
return myOrderDao.getOrderListByStatusAndAdminUserId(status,
adminUserId);
}
@Override
public Boolean cancelMyOrder(Order order, MyCustomer myCustomer)
throws PricingException, ConcurrentInventoryModificationException {
if (order == null || myCustomer == null
|| order.getPaymentInfos() == null
|| order.getPaymentInfos().isEmpty()
|| order.getPaymentInfos().get(0) == null
|| OrderStatus.NAMED.equals(order.getStatus())
|| OrderStatus.IN_PROCESS.equals(order.getStatus())
|| OrderStatus.CANCELLED.equals(order.getStatus())) {
return null;
}
List<OrderItem> orderItems = order.getOrderItems();
for (int i = 0; i < orderItems.size(); i++) {
OrderItem item = orderItems.get(i);
Sku sku = null;
if (item instanceof SkuAccessor) {
sku = ((SkuAccessor) item).getSku();
}
FulfillmentLocation location = null;
if (item instanceof LocationedItem) {
location = ((LocationedItem) item).getLocation();
}
Map<Sku, Integer> skuInventoryMap = new HashMap<Sku, Integer>(1);
skuInventoryMap.put(sku, item.getQuantity());
if (location == null) {
inventoryService.incrementInventory(skuInventoryMap);
inventoryService.incrementInventoryOnHand(skuInventoryMap);
} else {
inventoryService.incrementInventory(skuInventoryMap, location);
inventoryService.incrementInventoryOnHand(skuInventoryMap,
location);
}
}
order.setStatus(OrderStatus.CANCELLED);
super.save(order, true);
// 退钱
if (!"CNY".equals(order.getCurrency().getCurrencyCode())) {
return Boolean.TRUE;
}
for (PaymentInfo info : order.getPaymentInfos()) {
if (!MyPaymentInfoType.Payment_Cod.equals(info.getType())) {
myCustomerService.rechargeToAccountBalance(myCustomer.getId(),
info.getAmount().getAmount(), BalanceChangeType.BPBACK);
}
}
return Boolean.TRUE;
}
@Override
public List<Order> getAllOrdersAfterSubmitted(Long customerId) {
return myOrderDao.getAllOrdersAfterSubmitted(customerId);
}
public List<Order> getOrderbyIds(Long[] orderIds) {
return myOrderDao.getOrderbyIds(orderIds);
}
@SuppressWarnings("deprecation")
@Transactional("blTransactionManager")
@Override
public Boolean cancelOrderItem(OrderItem orderItem, MyCustomer myCustomer,
long quantity) throws ConcurrentInventoryModificationException {
// quantity要大于等于0小于原订单单项的数量,不是人民币的不能退
if (orderItem == null
|| orderItem.getOrder() == null
|| myCustomer == null
|| quantity < 0
|| OrderStatus.NAMED.equals(orderItem.getOrder().getStatus())
|| OrderStatus.IN_PROCESS.equals(orderItem.getOrder()
.getStatus())
|| OrderStatus.CANCELLED.equals(orderItem.getOrder()
.getStatus())) {
return null;
}
Order order = orderItem.getOrder();
FulfillmentLocation location = null;
if (orderItem instanceof LocationedItem)
location = ((LocationedItem) orderItem).getLocation();
Sku sku = null;
if (orderItem instanceof SkuAccessor) {
SkuAccessor item = (SkuAccessor) orderItem;
sku = item.getSku();
} else
return null;
double orderTotal = order.getTotal().doubleValue();
int oldQuantity = orderItem.getQuantity();
if (quantity == 0) {
if (LOG.isInfoEnabled()) {
LOG.info("该Orderitem的商品实际购买数量为零,因此该orderItem会被删除,该OrderItem的信息如下:所属的orderId为:"
+ orderItem.getOrder().getId()
+ ";skuid="
+ sku.getId()
+ ";该OrderItem的原先数量是:"
+ orderItem.getQuantity()
+ ";该OrderItem更改后数量为0;该OrderItem取消前的总价为:"
+ orderItem.getTotalPrice()
+ ";该OrderItem的优惠为:"
+ orderItem.getAdjustmentValue());
}
}
OrderItemRequestDTO orderItemRequestDTO = new OrderItemRequestDTO();
orderItemRequestDTO.setOrderItemId(orderItem.getId());
orderItemRequestDTO.setSkuId(sku.getId());
orderItemRequestDTO.getItemAttributes().put(
LocationedItem.LOCATIONED_ITEM_LOCATION_ID,
"" + (location == null ? -1 : location.getId()));
orderItemRequestDTO.setQuantity((int) quantity);
try {
order = super.updateItemQuantity(order.getId(),
orderItemRequestDTO, true);
} catch (UpdateCartException e1) {
LOG.error("UpdateCartException,更改数量数显异常", e1);
return Boolean.FALSE;
} catch (RemoveFromCartException e1) {
LOG.error("RemoveFromCartException,更改数量数显异常", e1);
return Boolean.FALSE;
}
// 退库存
Map<Sku, Integer> skuInventoryMap = new HashMap<Sku, Integer>(1);
skuInventoryMap.put(sku, (int) (oldQuantity - quantity));
if (location == null) {
inventoryService.incrementInventory(skuInventoryMap);
inventoryService.incrementInventoryOnHand(skuInventoryMap);
} else {
inventoryService.incrementInventory(skuInventoryMap, location);
inventoryService
.incrementInventoryOnHand(skuInventoryMap, location);
}
// 退钱
if (!"CNY".equals(order.getCurrency().getCurrencyCode())) {
return Boolean.TRUE;
}
double delta = orderTotal - order.getTotal().doubleValue();
for (PaymentInfo info : order.getPaymentInfos()) {
if (MyPaymentInfoType.Payment_Cod.equals(info.getType())) {
// 后付款
delta -= info.getAmount().doubleValue();
if (delta >= 0)
info.setAmount(new Money(BigDecimal.ZERO, order
.getCurrency()));
else {
info.setAmount(new Money(new BigDecimal(-delta), order
.getCurrency()));
break;
}
} else { // 预付款,需要返余额
if (!"CNY".equals(info.getCurrency().getCurrencyCode()))
continue;
double reBalance = delta;
delta -= info.getAmount().doubleValue();
if (delta >= 0) {
info.setAmount(new Money(BigDecimal.ZERO, order
.getCurrency()));
reBalance = info.getAmount().doubleValue();
} else {
info.setAmount(new Money(new BigDecimal(-delta), order
.getCurrency()));
break;
}
// TODO 取消订单操作的type未定
myCustomerService
.rechargeToAccountBalance(myCustomer.getId(),
BigDecimal.valueOf(reBalance),
BalanceChangeType.BPBACK);
}
}
return Boolean.TRUE;
}
@Override
public List<Order> getAllSubmittedInTime(Long customerID, Date begintime,
Date endtime) {
return myOrderDao.getAllOrdersAfterSubmittedIntime(customerID,
begintime, endtime);
}
@Override
public Order addItemFromNamedOrder(Order namedOrder, OrderItem item,
int quantity, boolean priceOrder) throws RemoveFromCartException,
AddToCartException, UpdateCartException {
// Validate that the quantity requested makes sense
if (quantity < 1 || quantity > item.getQuantity()) {
throw new IllegalArgumentException("Cannot move 0 or less quantity");
} else if (quantity == item.getQuantity()) {
return addItemFromNamedOrder(namedOrder, item, priceOrder);
}
Order cartOrder = orderDao
.readCartForCustomer(namedOrder.getCustomer());
if (cartOrder == null) {
cartOrder = createNewCartForCustomer(namedOrder.getCustomer());
}
if (moveNamedOrderItems) {
// Update the old item to its new quantity only if we're moving
// items
OrderItemRequestDTO orderItemRequestDTO = new OrderItemRequestDTO();
if (item instanceof LocationedItem) {
orderItemRequestDTO.getItemAttributes().put(
LocationedItem.LOCATIONED_ITEM_LOCATION_ID,
"" + ((LocationedItem) item).getLocation().getId());
}
orderItemRequestDTO.setOrderItemId(item.getId());
orderItemRequestDTO.setQuantity(item.getQuantity() - quantity);
updateItemQuantity(namedOrder.getId(), orderItemRequestDTO, false);
}
OrderItemRequestDTO orderItemRequest = orderItemService
.buildOrderItemRequestDTOFromOrderItem(item);
orderItemRequest.setQuantity(quantity);
cartOrder = addItem(cartOrder.getId(), orderItemRequest, priceOrder);
return cartOrder;
}
}