mirror of https://github.com/jeecgboot/jeecg-boot
Merge pull request #173 from LQYBill/feat/skuOrderClient
feat: client sku purchase access, purchase invoice USD fix, complete …pull/8523/head
commit
94b475d981
|
@ -8,6 +8,7 @@ import freemarker.template.Template;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.http.HttpStatus;
|
||||||
import org.apache.shiro.SecurityUtils;
|
import org.apache.shiro.SecurityUtils;
|
||||||
import org.jeecg.common.api.vo.Result;
|
import org.jeecg.common.api.vo.Result;
|
||||||
import org.jeecg.common.aspect.annotation.AutoLog;
|
import org.jeecg.common.aspect.annotation.AutoLog;
|
||||||
|
@ -58,6 +59,8 @@ import static org.jeecg.common.util.SqlInjectionUtil.specialFilterContentForDict
|
||||||
@RequestMapping("/sku")
|
@RequestMapping("/sku")
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class SkuController {
|
public class SkuController {
|
||||||
|
@Autowired
|
||||||
|
private IClientService clientService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private IShopService shopService;
|
private IShopService shopService;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@ -75,6 +78,8 @@ public class SkuController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private SkuMongoService skuMongoService;
|
private SkuMongoService skuMongoService;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
private ISecurityService securityService;
|
||||||
|
@Autowired
|
||||||
private EmailService emailService;
|
private EmailService emailService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private FreeMarkerConfigurer freemarkerConfigurer;
|
private FreeMarkerConfigurer freemarkerConfigurer;
|
||||||
|
@ -380,6 +385,19 @@ public class SkuController {
|
||||||
@RequestParam(name = "zhNames", required = false) String zhNames,
|
@RequestParam(name = "zhNames", required = false) String zhNames,
|
||||||
@RequestParam(name = "enNames", required = false) String enNames,
|
@RequestParam(name = "enNames", required = false) String enNames,
|
||||||
ServletRequest servletRequest) {
|
ServletRequest servletRequest) {
|
||||||
|
if(!securityService.checkIsEmployee()) {
|
||||||
|
Client client = clientService.getCurrentClient();
|
||||||
|
// Here we don't explicitly tell the user that they are not allowed to access this endpoint for security measure.
|
||||||
|
if (client == null) {
|
||||||
|
return Result.error(HttpStatus.SC_NOT_FOUND, "Profile not found");
|
||||||
|
}
|
||||||
|
if( clientId == null) {
|
||||||
|
return Result.error(HttpStatus.SC_BAD_REQUEST, "Bad request");
|
||||||
|
}
|
||||||
|
if(!client.getId().equals(clientId)) {
|
||||||
|
return Result.error(HttpStatus.SC_NOT_FOUND, "Client not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
String parsedColumn = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, column.replace("_dictText", ""));
|
String parsedColumn = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, column.replace("_dictText", ""));
|
||||||
String parsedOrder = order.toUpperCase();
|
String parsedOrder = order.toUpperCase();
|
||||||
if(!parsedOrder.equals("ASC") && !parsedOrder.equals("DESC")) {
|
if(!parsedOrder.equals("ASC") && !parsedOrder.equals("DESC")) {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import freemarker.template.Template;
|
||||||
import freemarker.template.TemplateException;
|
import freemarker.template.TemplateException;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.http.HttpStatus;
|
||||||
import org.apache.shiro.SecurityUtils;
|
import org.apache.shiro.SecurityUtils;
|
||||||
import org.jeecg.common.api.vo.Result;
|
import org.jeecg.common.api.vo.Result;
|
||||||
import org.jeecg.common.system.query.QueryGenerator;
|
import org.jeecg.common.system.query.QueryGenerator;
|
||||||
|
@ -76,6 +77,8 @@ public class InvoiceController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private IClientService clientService;
|
private IClientService clientService;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
private IClientSkuService clientSkuService;
|
||||||
|
@Autowired
|
||||||
private ICurrencyService currencyService;
|
private ICurrencyService currencyService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private ExchangeRatesMapper exchangeRatesMapper;
|
private ExchangeRatesMapper exchangeRatesMapper;
|
||||||
|
@ -383,12 +386,12 @@ public class InvoiceController {
|
||||||
*/
|
*/
|
||||||
@Transactional
|
@Transactional
|
||||||
@PostMapping(value = "/makeManualComplete")
|
@PostMapping(value = "/makeManualComplete")
|
||||||
public Result<?> makeManualCompleteInvoice(@RequestBody ShippingInvoiceOrderParam param) {
|
public Result<?> makeManualCompleteInvoice(@RequestBody ManualInvoiceOrderParam param) {
|
||||||
try {
|
try {
|
||||||
InvoiceMetaData metaData = shippingInvoiceService.makeCompleteInvoice(param);
|
InvoiceMetaData metaData = shippingInvoiceService.makeManualCompleteInvoice(param);
|
||||||
String clientCategory = clientCategoryService.getClientCategoryByClientId(param.clientID());
|
String clientCategory = clientCategoryService.getClientCategoryByClientId(param.getClientID());
|
||||||
if(clientCategory.equals(ClientCategory.CategoryName.CONFIRMED.getName()) || clientCategory.equals(ClientCategory.CategoryName.VIP.getName())) {
|
if(clientCategory.equals(ClientCategory.CategoryName.CONFIRMED.getName()) || clientCategory.equals(ClientCategory.CategoryName.VIP.getName())) {
|
||||||
balanceService.updateBalance(param.clientID(), metaData.getInvoiceCode(), COMPLETE.name());
|
balanceService.updateBalance(param.getClientID(), metaData.getInvoiceCode(), COMPLETE.name());
|
||||||
}
|
}
|
||||||
if(clientCategory.equals(ClientCategory.CategoryName.SELF_SERVICE.getName())) {
|
if(clientCategory.equals(ClientCategory.CategoryName.SELF_SERVICE.getName())) {
|
||||||
String subject = "Self-service complete invoice";
|
String subject = "Self-service complete invoice";
|
||||||
|
@ -396,7 +399,7 @@ public class InvoiceController {
|
||||||
Properties prop = emailService.getMailSender();
|
Properties prop = emailService.getMailSender();
|
||||||
Map<String, Object> templateModel = new HashMap<>();
|
Map<String, Object> templateModel = new HashMap<>();
|
||||||
templateModel.put("invoiceType", "complete invoice");
|
templateModel.put("invoiceType", "complete invoice");
|
||||||
templateModel.put("invoiceEntity", clientService.getById(param.clientID()).getInternalCode());
|
templateModel.put("invoiceEntity", clientService.getById(param.getClientID()).getInternalCode());
|
||||||
templateModel.put("invoiceNumber", metaData.getInvoiceCode());
|
templateModel.put("invoiceNumber", metaData.getInvoiceCode());
|
||||||
|
|
||||||
Session session = Session.getInstance(prop, new Authenticator() {
|
Session session = Session.getInstance(prop, new Authenticator() {
|
||||||
|
@ -423,10 +426,22 @@ public class InvoiceController {
|
||||||
}
|
}
|
||||||
@PostMapping("/makeManualSkuPurchaseInvoice")
|
@PostMapping("/makeManualSkuPurchaseInvoice")
|
||||||
public Result<?> createOrder(@RequestBody Map<String, Integer> payload) {
|
public Result<?> createOrder(@RequestBody Map<String, Integer> payload) {
|
||||||
|
boolean isEmployee = securityService.checkIsEmployee();
|
||||||
|
Client client = null;
|
||||||
|
if(!isEmployee) {
|
||||||
|
client = clientService.getCurrentClient();
|
||||||
|
if(client == null)
|
||||||
|
return Result.error(HttpStatus.SC_NOT_FOUND, "Client not found");
|
||||||
|
}
|
||||||
InvoiceMetaData metaData;
|
InvoiceMetaData metaData;
|
||||||
List<SkuQuantity> skuQuantities = new ArrayList<>();
|
List<SkuQuantity> skuQuantities = new ArrayList<>();
|
||||||
for(Map.Entry<String, Integer> entry : payload.entrySet()) {
|
for(Map.Entry<String, Integer> entry : payload.entrySet()) {
|
||||||
String skuId = skuService.getIdFromErpCode(entry.getKey());
|
String skuId = skuService.getIdFromErpCode(entry.getKey());
|
||||||
|
if(client != null) {
|
||||||
|
String skuClientId = clientSkuService.getClientIdFromSkuId(skuId);
|
||||||
|
if (!skuClientId.equals(client.getId()))
|
||||||
|
return Result.error(HttpStatus.SC_NOT_FOUND, "Sku " + entry.getKey() + " for client " + client.getInternalCode() + " not found.");
|
||||||
|
}
|
||||||
skuQuantities.add(new SkuQuantity(skuId, entry.getKey(), entry.getValue()));
|
skuQuantities.add(new SkuQuantity(skuId, entry.getKey(), entry.getValue()));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class MabangOrderSyncJob implements Job {
|
||||||
}
|
}
|
||||||
username = jsonObject.getString("username");
|
username = jsonObject.getString("username");
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
log.error("Error while parsing parameter as JSON, falling back to default parameters.");
|
log.error("Error while parsing parameter as JSON, falling back to default parameters : {}", e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (platformOrderIds.isEmpty()) {
|
if (platformOrderIds.isEmpty()) {
|
||||||
|
|
|
@ -42,6 +42,8 @@ import static org.jeecg.modules.business.entity.Invoice.InvoicingMethod.*;
|
||||||
@Component
|
@Component
|
||||||
public class ShippingInvoiceFactory {
|
public class ShippingInvoiceFactory {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IClientService clientService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private IExtraFeeService extraFeeService;
|
private IExtraFeeService extraFeeService;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@ -99,6 +101,7 @@ public class ShippingInvoiceFactory {
|
||||||
return skuDeclaredValueService.getDeclaredValueForDate(skuIdAndDate.getLeft(), skuIdAndDate.getRight());
|
return skuDeclaredValueService.getDeclaredValueForDate(skuIdAndDate.getLeft(), skuIdAndDate.getRight());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
private final List<String> CLIENT_STOCK_BYPASS_LIST = Arrays.asList("LA", "AP");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an invoice for a client according to type
|
* Creates an invoice for a client according to type
|
||||||
|
@ -149,6 +152,7 @@ public class ShippingInvoiceFactory {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a complete shipping (purchase + shipping) invoice for a client
|
* Creates a complete shipping (purchase + shipping) invoice for a client
|
||||||
|
* /!\ if the client is in the bypass list and ordersWithStock is not empty we only invoice the shipping fee of these orders, and we don't invoice the purchase fee
|
||||||
* <p>
|
* <p>
|
||||||
* To generate an invoice, it
|
* To generate an invoice, it
|
||||||
* <ol>
|
* <ol>
|
||||||
|
@ -164,12 +168,13 @@ public class ShippingInvoiceFactory {
|
||||||
* @param customerId the customer id
|
* @param customerId the customer id
|
||||||
* @param orderIds the list of order IDs
|
* @param orderIds the list of order IDs
|
||||||
* @param shippingMethod "post" = postShipping, "pre" = preShipping, "all" = all shipping methods
|
* @param shippingMethod "post" = postShipping, "pre" = preShipping, "all" = all shipping methods
|
||||||
|
* @param ordersWithStock for orders with stock, if the client is in the bypass list, we only invoice the shipping fee and we don't invoice the purchase fee of the orders with stock
|
||||||
* @return the generated invoice
|
* @return the generated invoice
|
||||||
* @throws UserException if package used by the invoice can not or find more than 1 logistic
|
* @throws UserException if package used by the invoice can not or find more than 1 logistic
|
||||||
* channel price, this exception will be thrown.
|
* channel price, this exception will be thrown.
|
||||||
*/
|
*/
|
||||||
@Transactional
|
@Transactional
|
||||||
public CompleteInvoice createCompleteShippingInvoice(String username, String customerId, BigDecimal balance, List<String> orderIds, String shippingMethod, String start, String end) throws UserException, MessagingException, InterruptedException {
|
public CompleteInvoice createCompleteShippingInvoice(String username, String customerId, BigDecimal balance, List<String> orderIds, String shippingMethod, String start, String end, List<String> ordersWithStock) throws UserException, MessagingException, InterruptedException {
|
||||||
log.info("Creating a complete invoice for \n client ID: {}, order IDs: {}]", customerId, orderIds);
|
log.info("Creating a complete invoice for \n client ID: {}, order IDs: {}]", customerId, orderIds);
|
||||||
// find orders and their contents of the invoice
|
// find orders and their contents of the invoice
|
||||||
Map<PlatformOrder, List<PlatformOrderContent>> uninvoicedOrderToContent = platformOrderService.fetchUninvoicedOrderDataForUpdate(orderIds);
|
Map<PlatformOrder, List<PlatformOrderContent>> uninvoicedOrderToContent = platformOrderService.fetchUninvoicedOrderDataForUpdate(orderIds);
|
||||||
|
@ -184,19 +189,32 @@ public class ShippingInvoiceFactory {
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
List<ExtraFeeResult> extraFees = extraFeeService.findNotInvoicedByShops(shopIds);
|
List<ExtraFeeResult> extraFees = extraFeeService.findNotInvoicedByShops(shopIds);
|
||||||
log.info("Orders to be invoiced: {}", uninvoicedOrderToContent);
|
log.info("Orders to be invoiced: {}", uninvoicedOrderToContent);
|
||||||
String subject;
|
StringBuilder subject = new StringBuilder();
|
||||||
if(shippingMethod.equals("shipping"))
|
boolean hasPeriod = start != null && !start.isEmpty() && end != null && !end.isEmpty();
|
||||||
subject = String.format("Purchase and Shipping fees from %s to %s", start, end);
|
if(shippingMethod.equals("shipping")) {
|
||||||
else if(shippingMethod.equals(POSTSHIPPING.getMethod()))
|
subject.append("Purchase and Shipping fees");
|
||||||
subject = String.format("Purchase and post-Shipping fees from %s to %s", start, end);
|
if(hasPeriod)
|
||||||
else if (shippingMethod.equals(PRESHIPPING.getMethod()))
|
subject.append(String.format(" from %s to %s", start, end));
|
||||||
subject = String.format("Purchase and pre-Shipping fees, order time from %s to %s", start, end);
|
}
|
||||||
else if(shippingMethod.equals(ALL.getMethod()))
|
else if(shippingMethod.equals(POSTSHIPPING.getMethod())) {
|
||||||
subject = String.format("Purchase and Shipping fees, order time from %s to %s", start, end);
|
subject.append("Purchase and post-Shipping fees");
|
||||||
|
if(hasPeriod)
|
||||||
|
subject.append(String.format(" from %s to %s", start, end));
|
||||||
|
}
|
||||||
|
else if (shippingMethod.equals(PRESHIPPING.getMethod())) {
|
||||||
|
subject.append("Purchase and Pre-Shipping fees");
|
||||||
|
if(hasPeriod)
|
||||||
|
subject.append(String.format(" order time from %s to %s", start, end));
|
||||||
|
}
|
||||||
|
else if(shippingMethod.equals(ALL.getMethod())) {
|
||||||
|
subject.append("Purchase and Shipping fees");
|
||||||
|
if(hasPeriod)
|
||||||
|
subject.append(String.format(" order time from %s to %s", start, end));
|
||||||
|
}
|
||||||
else throw new UserException("Couldn't create complete invoice for unknown shipping method");
|
else throw new UserException("Couldn't create complete invoice for unknown shipping method");
|
||||||
if(balance != null)
|
if(balance != null)
|
||||||
return createCompleteInvoiceWithBalance(username, customerId, balance, shopIds, uninvoicedOrderToContent, savRefunds, extraFees, subject);
|
return createCompleteInvoiceWithBalance(username, customerId, balance, shopIds, uninvoicedOrderToContent, savRefunds, extraFees, subject.toString());
|
||||||
return createInvoice(username, customerId, null, shopIds, uninvoicedOrderToContent, savRefunds, extraFees, subject);
|
return createInvoice(username, customerId, null, shopIds, uninvoicedOrderToContent, savRefunds, extraFees, subject.toString(), ordersWithStock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -225,7 +243,7 @@ public class ShippingInvoiceFactory {
|
||||||
@Transactional
|
@Transactional
|
||||||
public CompleteInvoice createInvoice(String username, String customerId, BigDecimal balance, List<String> shopIds,
|
public CompleteInvoice createInvoice(String username, String customerId, BigDecimal balance, List<String> shopIds,
|
||||||
Map<PlatformOrder, List<PlatformOrderContent>> orderAndContent,
|
Map<PlatformOrder, List<PlatformOrderContent>> orderAndContent,
|
||||||
List<SavRefundWithDetail> savRefunds, List<ExtraFeeResult> extraFees, String subject) throws UserException {
|
List<SavRefundWithDetail> savRefunds, List<ExtraFeeResult> extraFees, String subject, List<String> ordersWithStock) throws UserException {
|
||||||
Client client = clientMapper.selectById(customerId);
|
Client client = clientMapper.selectById(customerId);
|
||||||
log.info("User {} is creating a complete invoice for customer {}", username, client.getInternalCode());
|
log.info("User {} is creating a complete invoice for customer {}", username, client.getInternalCode());
|
||||||
|
|
||||||
|
@ -251,14 +269,22 @@ public class ShippingInvoiceFactory {
|
||||||
log.info("New invoice code: {}", invoiceCode);
|
log.info("New invoice code: {}", invoiceCode);
|
||||||
calculateFees(balance, logisticChannelMap, orderAndContent, channelPriceMap, countryList, skuRealWeights, skuServiceFees,
|
calculateFees(balance, logisticChannelMap, orderAndContent, channelPriceMap, countryList, skuRealWeights, skuServiceFees,
|
||||||
latestDeclaredValues, client, shopServiceFeeMap, shopPackageMatFeeMap, invoiceCode);
|
latestDeclaredValues, client, shopServiceFeeMap, shopPackageMatFeeMap, invoiceCode);
|
||||||
|
// Purchase fees
|
||||||
BigDecimal eurToUsd = exchangeRatesMapper.getLatestExchangeRate("EUR", "USD");
|
BigDecimal eurToUsd = exchangeRatesMapper.getLatestExchangeRate("EUR", "USD");
|
||||||
List<String> orderIds = orderAndContent.keySet().stream().map(PlatformOrder::getId).collect(toList());
|
List<String> orderIds = orderAndContent.keySet().stream().map(PlatformOrder::getId).collect(toList());
|
||||||
|
List<PurchaseInvoiceEntry> purchaseOrderSkuList = new ArrayList<>();
|
||||||
|
List<PromotionDetail> promotionDetails = new ArrayList<>();
|
||||||
|
List<String> clientsThatByPassStock = clientService.getClientsByCode(CLIENT_STOCK_BYPASS_LIST);
|
||||||
|
if(clientsThatByPassStock.contains(customerId) && ordersWithStock != null && !ordersWithStock.isEmpty()) {
|
||||||
|
orderIds = orderIds.stream().filter(orderId -> !ordersWithStock.contains(orderId)).collect(toList());
|
||||||
|
}
|
||||||
|
if(!orderIds.isEmpty()){
|
||||||
List<SkuQuantity> skuQuantities = platformOrderContentService.searchOrderContent(orderIds);
|
List<SkuQuantity> skuQuantities = platformOrderContentService.searchOrderContent(orderIds);
|
||||||
|
|
||||||
String purchaseID = purchaseOrderService.addPurchase(username, client, invoiceCode, skuQuantities, orderAndContent);
|
String purchaseID = purchaseOrderService.addPurchase(username, client, invoiceCode, skuQuantities, orderAndContent, ordersWithStock);
|
||||||
|
|
||||||
List<PurchaseInvoiceEntry> purchaseOrderSkuList = purchaseOrderContentMapper.selectInvoiceDataByID(purchaseID);
|
purchaseOrderSkuList = purchaseOrderContentMapper.selectInvoiceDataByID(purchaseID);
|
||||||
List<PromotionDetail> promotionDetails = skuPromotionHistoryMapper.selectPromotionByPurchase(purchaseID);
|
promotionDetails = skuPromotionHistoryMapper.selectPromotionByPurchase(purchaseID);
|
||||||
if (savRefunds != null) {
|
if (savRefunds != null) {
|
||||||
updateSavRefundsInDb(savRefunds, invoiceCode);
|
updateSavRefundsInDb(savRefunds, invoiceCode);
|
||||||
}
|
}
|
||||||
|
@ -266,6 +292,7 @@ public class ShippingInvoiceFactory {
|
||||||
List<String> extraFeesIds = extraFees.stream().map(ExtraFeeResult::getId).collect(toList());
|
List<String> extraFeesIds = extraFees.stream().map(ExtraFeeResult::getId).collect(toList());
|
||||||
extraFeeService.updateInvoiceNumberByIds(extraFeesIds, invoiceCode);
|
extraFeeService.updateInvoiceNumberByIds(extraFeesIds, invoiceCode);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
updateOrdersAndContentsInDb(orderAndContent);
|
updateOrdersAndContentsInDb(orderAndContent);
|
||||||
|
|
||||||
return new CompleteInvoice(client, invoiceCode, subject, orderAndContent, savRefunds, extraFees,
|
return new CompleteInvoice(client, invoiceCode, subject, orderAndContent, savRefunds, extraFees,
|
||||||
|
@ -391,7 +418,7 @@ public class ShippingInvoiceFactory {
|
||||||
List<String> orderIds = orderAndContent.keySet().stream().map(PlatformOrder::getId).collect(toList());
|
List<String> orderIds = orderAndContent.keySet().stream().map(PlatformOrder::getId).collect(toList());
|
||||||
List<SkuQuantity> skuQuantities = platformOrderContentService.searchOrderContent(orderIds);
|
List<SkuQuantity> skuQuantities = platformOrderContentService.searchOrderContent(orderIds);
|
||||||
|
|
||||||
String purchaseID = purchaseOrderService.addPurchase(username, client, invoiceCode, skuQuantities, orderAndContent);
|
String purchaseID = purchaseOrderService.addPurchase(username, client, invoiceCode, skuQuantities, orderAndContent, null);
|
||||||
|
|
||||||
List<PurchaseInvoiceEntry> purchaseOrderSkuList = purchaseOrderContentMapper.selectInvoiceDataByID(purchaseID);
|
List<PurchaseInvoiceEntry> purchaseOrderSkuList = purchaseOrderContentMapper.selectInvoiceDataByID(purchaseID);
|
||||||
List<PromotionDetail> promotionDetails = skuPromotionHistoryMapper.selectPromotionByPurchase(purchaseID);
|
List<PromotionDetail> promotionDetails = skuPromotionHistoryMapper.selectPromotionByPurchase(purchaseID);
|
||||||
|
|
|
@ -38,4 +38,6 @@ public interface ClientMapper extends BaseMapper<Client> {
|
||||||
Client getByShopId(@Param("shopId") String shopId);
|
Client getByShopId(@Param("shopId") String shopId);
|
||||||
|
|
||||||
Client getClientFromCredit(@Param("invoiceNumber") String invoiceNumber);
|
Client getClientFromCredit(@Param("invoiceNumber") String invoiceNumber);
|
||||||
|
|
||||||
|
List<String> getClientsByCode(@Param("codes") List<String> clientCodes);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,4 +21,6 @@ public interface ClientSkuMapper extends BaseMapper<ClientSku> {
|
||||||
List<ClientSku> selectByMainId(@Param("mainId") String mainId);
|
List<ClientSku> selectByMainId(@Param("mainId") String mainId);
|
||||||
|
|
||||||
List<Sku> getUnpairedSkus();
|
List<Sku> getUnpairedSkus();
|
||||||
|
|
||||||
|
String getClientIdFromSkuId(@Param("skuId") String skuId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,4 +107,13 @@
|
||||||
JOIN credit ON c.id = credit.client_id
|
JOIN credit ON c.id = credit.client_id
|
||||||
WHERE credit.invoice_number = #{invoiceNumber};
|
WHERE credit.invoice_number = #{invoiceNumber};
|
||||||
</select>
|
</select>
|
||||||
|
<select id="getClientsByCode" resultType="java.lang.String">
|
||||||
|
SELECT c.id
|
||||||
|
FROM client c
|
||||||
|
WHERE c.internal_code IN
|
||||||
|
<foreach collection="codes" item="code" index="index" separator="," open="(" close=")">
|
||||||
|
#{code}
|
||||||
|
</foreach>
|
||||||
|
AND c.active = 1;
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
|
@ -2,22 +2,28 @@
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="org.jeecg.modules.business.mapper.ClientSkuMapper">
|
<mapper namespace="org.jeecg.modules.business.mapper.ClientSkuMapper">
|
||||||
|
|
||||||
<delete id="deleteByMainId" parameterType="java.lang.String">
|
<delete id="deleteByMainId" parameterType="java.lang.String">
|
||||||
DELETE
|
DELETE
|
||||||
FROM client_sku
|
FROM client_sku
|
||||||
WHERE
|
WHERE
|
||||||
client_id = #{mainId} </delete>
|
client_id = #{mainId}
|
||||||
|
</delete>
|
||||||
|
|
||||||
<select id="selectByMainId" parameterType="java.lang.String" resultType="org.jeecg.modules.business.entity.ClientSku">
|
<select id="selectByMainId" parameterType="java.lang.String" resultType="org.jeecg.modules.business.entity.ClientSku">
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM client_sku
|
FROM client_sku
|
||||||
WHERE
|
WHERE
|
||||||
client_id = #{mainId} </select>
|
client_id = #{mainId} </select>
|
||||||
|
|
||||||
<select id="getUnpairedSkus" resultType="org.jeecg.modules.business.entity.Sku">
|
<select id="getUnpairedSkus" resultType="org.jeecg.modules.business.entity.Sku">
|
||||||
SELECT s.*
|
SELECT s.*
|
||||||
FROM sku s
|
FROM sku s
|
||||||
LEFT JOIN client_sku cs ON s.id = cs.sku_id
|
LEFT JOIN client_sku cs ON s.id = cs.sku_id
|
||||||
WHERE cs.sku_id IS NULL;
|
WHERE cs.sku_id IS NULL;
|
||||||
</select>
|
</select>
|
||||||
|
<select id="getClientIdFromSkuId" resultType="java.lang.String">
|
||||||
|
SELECT client_id
|
||||||
|
FROM client_sku
|
||||||
|
WHERE sku_id = #{skuId}
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
|
@ -184,10 +184,16 @@
|
||||||
JOIN shop s ON po.shop_id = s.id
|
JOIN shop s ON po.shop_id = s.id
|
||||||
JOIN client c ON s.owner_id = c.id
|
JOIN client c ON s.owner_id = c.id
|
||||||
WHERE c.id = #{clientId}
|
WHERE c.id = #{clientId}
|
||||||
|
AND poc.create_time >= '2024-01-01 00:00:00'
|
||||||
AND po.erp_status IN ('1','2')
|
AND po.erp_status IN ('1','2')
|
||||||
AND po.can_send = 1
|
AND po.can_send = 1
|
||||||
AND poc.erp_status IN ('1','2')
|
AND poc.erp_status IN ('1','2')
|
||||||
GROUP BY sku_id
|
GROUP BY sku_id
|
||||||
|
), latest_exchange_rate AS (
|
||||||
|
SELECT rate
|
||||||
|
FROM exchange_rates
|
||||||
|
WHERE original_currency = 'EUR' AND target_currency = 'RMB'
|
||||||
|
ORDER BY create_time DESC LIMIT 1
|
||||||
), rmb_id AS (
|
), rmb_id AS (
|
||||||
SELECT id FROM currency WHERE code = 'RMB'
|
SELECT id FROM currency WHERE code = 'RMB'
|
||||||
)
|
)
|
||||||
|
@ -198,32 +204,25 @@
|
||||||
s.purchasing_amount,
|
s.purchasing_amount,
|
||||||
s.available_amount,
|
s.available_amount,
|
||||||
qtyInOrdersNotShipped.quantity as qtyInOrdersNotShipped,
|
qtyInOrdersNotShipped.quantity as qtyInOrdersNotShipped,
|
||||||
s.available_amount + s.purchasing_amount - IF(qtyInOrdersNotShipped.quantity IS NULL, 0, qtyInOrdersNotShipped.quantity) as stock,
|
s.available_amount + s.purchasing_amount - COALESCE(qtyInOrdersNotShipped.quantity, 0) as stock,
|
||||||
s.image_source,
|
s.image_source,
|
||||||
s.service_fee,
|
s.service_fee,
|
||||||
IF(sp.currency_id = (SELECT id FROM rmb_id),
|
IF(sp.currency_id = (SELECT id FROM rmb_id),
|
||||||
(
|
(
|
||||||
ROUND(
|
ROUND(
|
||||||
sp.price /
|
sp.price /
|
||||||
(SELECT rate
|
(SELECT rate FROM latest_exchange_rate)
|
||||||
FROM exchange_rates
|
|
||||||
WHERE original_currency = 'EUR' AND target_currency = 'RMB'
|
|
||||||
ORDER BY create_time DESC LIMIT 1)
|
|
||||||
,2)
|
,2)
|
||||||
),
|
), sp.price
|
||||||
sp.price
|
|
||||||
) as sku_price,
|
) as sku_price,
|
||||||
sp.threshold as discount_moq,
|
sp.threshold as discount_moq,
|
||||||
IF(sp.currency_id = (SELECT id FROM rmb_id),
|
IF(sp.currency_id = (SELECT id FROM rmb_id),
|
||||||
(
|
(
|
||||||
ROUND(
|
ROUND(
|
||||||
sp.discounted_price /
|
sp.discounted_price /
|
||||||
(SELECT rate
|
(SELECT rate FROM latest_exchange_rate)
|
||||||
FROM exchange_rates
|
|
||||||
WHERE target_currency = 'EUR' AND original_currency = 'RMB'
|
|
||||||
ORDER BY create_time DESC LIMIT 1)
|
|
||||||
,2)
|
,2)
|
||||||
), sp.discounted_price
|
),sp.discounted_price
|
||||||
) as discounted_price,
|
) as discounted_price,
|
||||||
s7.quantity as sales_last_week,
|
s7.quantity as sales_last_week,
|
||||||
s28.quantity as sales_four_weeks,
|
s28.quantity as sales_four_weeks,
|
||||||
|
@ -381,6 +380,11 @@
|
||||||
AND po.can_send = 1
|
AND po.can_send = 1
|
||||||
AND poc.erp_status IN ('1','2')
|
AND poc.erp_status IN ('1','2')
|
||||||
GROUP BY sku_id
|
GROUP BY sku_id
|
||||||
|
), latest_exchange_rate AS (
|
||||||
|
SELECT rate
|
||||||
|
FROM exchange_rates
|
||||||
|
WHERE original_currency = 'EUR' AND target_currency = 'RMB'
|
||||||
|
ORDER BY create_time DESC LIMIT 1
|
||||||
), rmb_id AS (
|
), rmb_id AS (
|
||||||
SELECT id FROM currency WHERE code = 'RMB'
|
SELECT id FROM currency WHERE code = 'RMB'
|
||||||
)
|
)
|
||||||
|
@ -391,17 +395,14 @@
|
||||||
s.purchasing_amount,
|
s.purchasing_amount,
|
||||||
s.available_amount,
|
s.available_amount,
|
||||||
qtyInOrdersNotShippedCTE.quantity as qtyInOrdersNotShipped,
|
qtyInOrdersNotShippedCTE.quantity as qtyInOrdersNotShipped,
|
||||||
s.available_amount + s.purchasing_amount - IF(qtyInOrdersNotShippedCTE.quantity IS NULL, 0, qtyInOrdersNotShippedCTE.quantity) as stock,
|
s.available_amount + s.purchasing_amount - COALESCE(qtyInOrdersNotShippedCTE.quantity, 0) as stock,
|
||||||
s.image_source,
|
s.image_source,
|
||||||
s.service_fee,
|
s.service_fee,
|
||||||
IF(sp.currency_id = (SELECT id FROM rmb_id),
|
IF(sp.currency_id = (SELECT id FROM rmb_id),
|
||||||
(
|
(
|
||||||
ROUND(
|
ROUND(
|
||||||
sp.price /
|
sp.price /
|
||||||
(SELECT rate
|
(SELECT rate FROM latest_exchange_rate)
|
||||||
FROM exchange_rates
|
|
||||||
WHERE original_currency = 'EUR' AND target_currency = 'RMB'
|
|
||||||
ORDER BY create_time DESC LIMIT 1)
|
|
||||||
,2)
|
,2)
|
||||||
), sp.price
|
), sp.price
|
||||||
) as sku_price,
|
) as sku_price,
|
||||||
|
@ -410,12 +411,9 @@
|
||||||
(
|
(
|
||||||
ROUND(
|
ROUND(
|
||||||
sp.discounted_price /
|
sp.discounted_price /
|
||||||
(SELECT rate
|
(SELECT rate FROM latest_exchange_rate)
|
||||||
FROM exchange_rates
|
|
||||||
WHERE target_currency = 'EUR' AND original_currency = 'RMB'
|
|
||||||
ORDER BY create_time DESC LIMIT 1)
|
|
||||||
,2)
|
,2)
|
||||||
), sp.discounted_price
|
),sp.discounted_price
|
||||||
) as discounted_price,
|
) as discounted_price,
|
||||||
s7.quantity as sales_last_week,
|
s7.quantity as sales_last_week,
|
||||||
s28.quantity as sales_four_weeks,
|
s28.quantity as sales_four_weeks,
|
||||||
|
@ -477,7 +475,7 @@
|
||||||
s.available_amount + s.purchasing_amount - IF(qtyInOrdersNotShippedCTE.quantity IS NULL, 0, qtyInOrdersNotShippedCTE.quantity) as stock,
|
s.available_amount + s.purchasing_amount - IF(qtyInOrdersNotShippedCTE.quantity IS NULL, 0, qtyInOrdersNotShippedCTE.quantity) as stock,
|
||||||
s.image_source,
|
s.image_source,
|
||||||
s.service_fee,
|
s.service_fee,
|
||||||
IF(sp.currency_id = (SELECT id FROM rmb_id) ,
|
IF(sp.currency_id = (SELECT id FROM rmb_id),
|
||||||
(
|
(
|
||||||
ROUND(
|
ROUND(
|
||||||
sp.price /
|
sp.price /
|
||||||
|
@ -485,8 +483,9 @@
|
||||||
FROM exchange_rates
|
FROM exchange_rates
|
||||||
WHERE original_currency = 'EUR' AND target_currency = 'RMB'
|
WHERE original_currency = 'EUR' AND target_currency = 'RMB'
|
||||||
ORDER BY create_time DESC LIMIT 1)
|
ORDER BY create_time DESC LIMIT 1)
|
||||||
,2)
|
,2
|
||||||
),sp.price,
|
)
|
||||||
|
), sp.price
|
||||||
) as sku_price,
|
) as sku_price,
|
||||||
sp.threshold as discount_moq,
|
sp.threshold as discount_moq,
|
||||||
IF(sp.currency_id = (SELECT id FROM rmb_id),
|
IF(sp.currency_id = (SELECT id FROM rmb_id),
|
||||||
|
@ -499,7 +498,7 @@
|
||||||
ORDER BY create_time DESC LIMIT 1)
|
ORDER BY create_time DESC LIMIT 1)
|
||||||
,2
|
,2
|
||||||
)
|
)
|
||||||
), sp.discounted_price,
|
), sp.discounted_price
|
||||||
) as discounted_price,
|
) as discounted_price,
|
||||||
s7.quantity as sales_last_week,
|
s7.quantity as sales_last_week,
|
||||||
s28.quantity as sales_four_weeks,
|
s28.quantity as sales_four_weeks,
|
||||||
|
|
|
@ -65,4 +65,6 @@ public interface IClientService extends IService<Client> {
|
||||||
Client getByShopId(String shopId);
|
Client getByShopId(String shopId);
|
||||||
|
|
||||||
Client getClientFromCredit(String invoiceNumber);
|
Client getClientFromCredit(String invoiceNumber);
|
||||||
|
|
||||||
|
List<String> getClientsByCode(List<String> clientCodes);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,4 +21,6 @@ public interface IClientSkuService extends IService<ClientSku> {
|
||||||
void addClientSku(String clientId, String skuId);
|
void addClientSku(String clientId, String skuId);
|
||||||
|
|
||||||
List<Sku> getUnpairedSkus();
|
List<Sku> getUnpairedSkus();
|
||||||
|
|
||||||
|
String getClientIdFromSkuId(String skuCode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ public interface IPurchaseOrderService extends IService<PurchaseOrder> {
|
||||||
String addPurchase(List<SkuQuantity> SkuQuantity, List<String> orderIDs) throws UserException;
|
String addPurchase(List<SkuQuantity> SkuQuantity, List<String> orderIDs) throws UserException;
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
String addPurchase(String username, Client client, String invoiceNumber, List<SkuQuantity> skuQuantities, Map<PlatformOrder, List<PlatformOrderContent>> platformOrderIDs) throws UserException;
|
String addPurchase(String username, Client client, String invoiceNumber, List<SkuQuantity> skuQuantities, Map<PlatformOrder, List<PlatformOrderContent>> orderContentMap, List<String> ordersWithStock) throws UserException;
|
||||||
|
|
||||||
void savePaymentDocumentForPurchase(String purchaseID, MultipartFile in) throws IOException;
|
void savePaymentDocumentForPurchase(String purchaseID, MultipartFile in) throws IOException;
|
||||||
|
|
||||||
|
|
|
@ -98,8 +98,10 @@ public class PlatformOrderShippingInvoiceService {
|
||||||
@Value("${jeecg.path.completeTemplatePath_US}")
|
@Value("${jeecg.path.completeTemplatePath_US}")
|
||||||
private String COMPLETE_INVOICE_TEMPLATE_US;
|
private String COMPLETE_INVOICE_TEMPLATE_US;
|
||||||
|
|
||||||
@Value("${jeecg.path.purchaseTemplatePath}")
|
@Value("${jeecg.path.purchaseTemplatePath_EU}")
|
||||||
private String PURCHASE_INVOICE_TEMPLATE;
|
private String PURCHASE_INVOICE_TEMPLATE_EU;
|
||||||
|
@Value("${jeecg.path.purchaseTemplatePath_US}")
|
||||||
|
private String PURCHASE_INVOICE_TEMPLATE_US;
|
||||||
|
|
||||||
@Value("${jeecg.path.shippingInvoiceDir}")
|
@Value("${jeecg.path.shippingInvoiceDir}")
|
||||||
private String INVOICE_DIR;
|
private String INVOICE_DIR;
|
||||||
|
@ -253,21 +255,11 @@ public class PlatformOrderShippingInvoiceService {
|
||||||
return getInvoiceMetaDataAndInsert(username, invoice);
|
return getInvoiceMetaDataAndInsert(username, invoice);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Make a complete shipping invoice (purchase + shipping) invoice for specified orders and order statuses
|
|
||||||
*
|
|
||||||
* @param param the parameters to make the invoice
|
|
||||||
* @return name of the invoice, can be used to in {@code getInvoiceBinary}.
|
|
||||||
* @throws UserException exception due to error of user input, message will contain detail
|
|
||||||
* @throws ParseException exception because of format of "start" and "end" date does not follow
|
|
||||||
* pattern: "yyyy-MM-dd"
|
|
||||||
* @throws IOException exception related to invoice file IO.
|
|
||||||
*/
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public InvoiceMetaData makeCompleteInvoice(ShippingInvoiceOrderParam param) throws UserException, ParseException, IOException, MessagingException, InterruptedException {
|
public InvoiceMetaData makeManualCompleteInvoice(ManualInvoiceOrderParam param) throws UserException, ParseException, IOException, MessagingException, InterruptedException {
|
||||||
String username = ((LoginUser) SecurityUtils.getSubject().getPrincipal()).getUsername();
|
String username = ((LoginUser) SecurityUtils.getSubject().getPrincipal()).getUsername();
|
||||||
// Creates invoice by factory
|
// Creates invoice by factory
|
||||||
CompleteInvoice invoice = factory.createCompleteShippingInvoice(username, param.clientID(), null, param.orderIds(), param.getType(), param.getStart(), param.getEnd());
|
CompleteInvoice invoice = factory.createCompleteShippingInvoice(username, param.getClientID(), null, param.getOrderIds(), param.getType(), null, null, param.getOrdersWithStock());
|
||||||
return getInvoiceMetaDataAndInsert(username, invoice);
|
return getInvoiceMetaDataAndInsert(username, invoice);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,7 +284,7 @@ public class PlatformOrderShippingInvoiceService {
|
||||||
orderIds = platformOrderMapper.fetchUninvoicedOrderIDInShopsAndOrderTime(param.getStart(), param.getEnd(), param.shopIDs(), param.getErpStatuses(), param.getWarehouses());
|
orderIds = platformOrderMapper.fetchUninvoicedOrderIDInShopsAndOrderTime(param.getStart(), param.getEnd(), param.shopIDs(), param.getErpStatuses(), param.getWarehouses());
|
||||||
}
|
}
|
||||||
// Creates invoice by factory
|
// Creates invoice by factory
|
||||||
CompleteInvoice invoice = factory.createCompleteShippingInvoice(username, param.clientID(), param.getBalance() ,orderIds, method, param.getStart(), param.getEnd());
|
CompleteInvoice invoice = factory.createCompleteShippingInvoice(username, param.clientID(), param.getBalance() ,orderIds, method, param.getStart(), param.getEnd(), null);
|
||||||
return getInvoiceMetaDataAndInsert(username, invoice);
|
return getInvoiceMetaDataAndInsert(username, invoice);
|
||||||
}
|
}
|
||||||
@NotNull
|
@NotNull
|
||||||
|
@ -341,8 +333,11 @@ public class PlatformOrderShippingInvoiceService {
|
||||||
@NotNull
|
@NotNull
|
||||||
private InvoiceMetaData getInvoiceMetaData(PurchaseInvoice invoice) throws IOException {
|
private InvoiceMetaData getInvoiceMetaData(PurchaseInvoice invoice) throws IOException {
|
||||||
// Chooses invoice template based on client's preference on currency
|
// Chooses invoice template based on client's preference on currency
|
||||||
Path template = Paths.get(PURCHASE_INVOICE_TEMPLATE );
|
Path template;
|
||||||
|
if(invoice.getTargetClient().getCurrency().equals("USD"))
|
||||||
|
template = Paths.get(PURCHASE_INVOICE_TEMPLATE_US );
|
||||||
|
else
|
||||||
|
template = Paths.get(PURCHASE_INVOICE_TEMPLATE_EU);
|
||||||
// Writes invoice content to a new excel file
|
// Writes invoice content to a new excel file
|
||||||
String filename = "Invoice N°" + invoice.getCode() + " (" + invoice.getTargetClient().getInvoiceEntity() + ").xlsx";
|
String filename = "Invoice N°" + invoice.getCode() + " (" + invoice.getTargetClient().getInvoiceEntity() + ").xlsx";
|
||||||
Path out = Paths.get(PURCHASE_INVOICE_DIR, filename);
|
Path out = Paths.get(PURCHASE_INVOICE_DIR, filename);
|
||||||
|
|
|
@ -64,6 +64,9 @@ public class BalanceServiceImpl extends ServiceImpl<BalanceMapper, Balance> impl
|
||||||
BigDecimal previousBalance = getBalanceByClientIdAndCurrency(clientId, currency);
|
BigDecimal previousBalance = getBalanceByClientIdAndCurrency(clientId, currency);
|
||||||
BigDecimal currentBalance = previousBalance.subtract(invoice.getFinalAmount());
|
BigDecimal currentBalance = previousBalance.subtract(invoice.getFinalAmount());
|
||||||
BigDecimal purchaseFees = purchaseOrderService.getPurchaseFeesByInvoiceCode(invoiceCode);
|
BigDecimal purchaseFees = purchaseOrderService.getPurchaseFeesByInvoiceCode(invoiceCode);
|
||||||
|
if(purchaseFees == null) {
|
||||||
|
purchaseFees = BigDecimal.ZERO;
|
||||||
|
}
|
||||||
currentBalance = currentBalance.subtract(purchaseFees);
|
currentBalance = currentBalance.subtract(purchaseFees);
|
||||||
SysUser sysUser = new SysUser();
|
SysUser sysUser = new SysUser();
|
||||||
Balance balance = Balance.of(sysUser.getUsername(), clientId, invoice.getCurrencyId(), Balance.OperationType.Debit.name(), invoice.getId(), currentBalance);
|
Balance balance = Balance.of(sysUser.getUsername(), clientId, invoice.getCurrencyId(), Balance.OperationType.Debit.name(), invoice.getId(), currentBalance);
|
||||||
|
|
|
@ -180,4 +180,9 @@ public class ClientServiceImpl extends ServiceImpl<ClientMapper, Client> impleme
|
||||||
public Client getClientFromCredit(String invoiceNumber) {
|
public Client getClientFromCredit(String invoiceNumber) {
|
||||||
return clientMapper.getClientFromCredit(invoiceNumber);
|
return clientMapper.getClientFromCredit(invoiceNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getClientsByCode(List<String> clientCodes) {
|
||||||
|
return clientMapper.getClientsByCode(clientCodes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,4 +86,9 @@ public class ClientSkuServiceImpl extends ServiceImpl<ClientSkuMapper, ClientSku
|
||||||
public List<Sku> getUnpairedSkus() {
|
public List<Sku> getUnpairedSkus() {
|
||||||
return clientSkuMapper.getUnpairedSkus();
|
return clientSkuMapper.getUnpairedSkus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClientIdFromSkuId(String skuId) {
|
||||||
|
return clientSkuMapper.getClientIdFromSkuId(skuId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,8 @@ public class InvoiceServiceImpl extends ServiceImpl<InvoiceMapper, Invoice> impl
|
||||||
else if(invoiceType.equalsIgnoreCase(COMPLETE.name())) {
|
else if(invoiceType.equalsIgnoreCase(COMPLETE.name())) {
|
||||||
ShippingInvoice shippingInvoice = shippingInvoiceService.getById(id);
|
ShippingInvoice shippingInvoice = shippingInvoiceService.getById(id);
|
||||||
PurchaseOrder purchase = purchaseOrderService.getPurchaseByInvoiceNumberAndClientId(invoiceNumber, clientId);
|
PurchaseOrder purchase = purchaseOrderService.getPurchaseByInvoiceNumberAndClientId(invoiceNumber, clientId);
|
||||||
if(shippingInvoice == null || purchase == null) {
|
// we don't test if purchase is null, because certain clients can have complete invoices without purchase orders, eg: LA, AP
|
||||||
|
if(shippingInvoice == null) {
|
||||||
log.error("Error while cancelling complete invoice : invoice or purchase not found for id : {}", id);
|
log.error("Error while cancelling complete invoice : invoice or purchase not found for id : {}", id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -143,23 +144,29 @@ public class InvoiceServiceImpl extends ServiceImpl<InvoiceMapper, Invoice> impl
|
||||||
log.error("Complete invoice {} older than {} days, client is not allowed to cancel it", invoiceNumber, CANCEL_DAYS_LIMIT);
|
log.error("Complete invoice {} older than {} days, client is not allowed to cancel it", invoiceNumber, CANCEL_DAYS_LIMIT);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(!isEmployee && purchase.isOrdered()) {
|
if(purchase != null) {
|
||||||
|
if (!isEmployee && purchase.isOrdered()) {
|
||||||
log.error("Purchase order {} for invoice {} is already ordered, cannot be cancelled", id, invoiceNumber);
|
log.error("Purchase order {} for invoice {} is already ordered, cannot be cancelled", id, invoiceNumber);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(purchase.getInventoryDocumentString() != null && !purchase.getInventoryDocumentString().isEmpty())
|
if (purchase.getInventoryDocumentString() != null && !purchase.getInventoryDocumentString().isEmpty())
|
||||||
shippingInvoiceService.deleteAttachmentFile(purchase.getInventoryDocumentString());
|
shippingInvoiceService.deleteAttachmentFile(purchase.getInventoryDocumentString());
|
||||||
if(purchase.getPaymentDocumentString() != null && !purchase.getPaymentDocumentString().isEmpty())
|
if (purchase.getPaymentDocumentString() != null && !purchase.getPaymentDocumentString().isEmpty())
|
||||||
shippingInvoiceService.deleteAttachmentFile(purchase.getPaymentDocumentString());
|
shippingInvoiceService.deleteAttachmentFile(purchase.getPaymentDocumentString());
|
||||||
|
purchaseOrderService.cancelInvoice(purchase.getId());
|
||||||
|
} else {
|
||||||
|
log.info("Purchase order not found for invoice : {}", invoiceNumber);
|
||||||
|
}
|
||||||
platformOrderContentService.cancelInvoice(invoiceNumber, clientId);
|
platformOrderContentService.cancelInvoice(invoiceNumber, clientId);
|
||||||
platformOrderMabangService.deleteOrderRemark(invoiceNumber);
|
platformOrderMabangService.deleteOrderRemark(invoiceNumber);
|
||||||
platformOrderService.removePurchaseInvoiceNumber(invoiceNumber, clientId);
|
platformOrderService.removePurchaseInvoiceNumber(invoiceNumber, clientId);
|
||||||
platformOrderService.cancelInvoice(invoiceNumber, clientId);
|
platformOrderService.cancelInvoice(invoiceNumber, clientId);
|
||||||
purchaseOrderService.cancelInvoice(purchase.getId());
|
|
||||||
shippingInvoiceService.cancelInvoice(id);
|
shippingInvoiceService.cancelInvoice(id);
|
||||||
|
|
||||||
// reminder : in complete invoicing balance is updated only once with shipping invoice ID and the amount is the sum of shipping fees and purchase fees
|
// reminder : in complete invoicing balance is updated only once with shipping invoice ID and the amount is the sum of shipping fees and purchase fees
|
||||||
amount = shippingInvoice.getFinalAmount().add(purchase.getFinalAmount());
|
amount = shippingInvoice.getFinalAmount();
|
||||||
|
if(purchase != null)
|
||||||
|
amount = amount.add(purchase.getFinalAmount());
|
||||||
currencyId = shippingInvoice.getCurrencyId();
|
currencyId = shippingInvoice.getCurrencyId();
|
||||||
}
|
}
|
||||||
else if(invoiceType.equalsIgnoreCase(CREDIT.name())) {
|
else if(invoiceType.equalsIgnoreCase(CREDIT.name())) {
|
||||||
|
|
|
@ -66,6 +66,8 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
|
||||||
private ICurrencyService currencyService;
|
private ICurrencyService currencyService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private IInvoiceNumberReservationService invoiceNumberReservationService;
|
private IInvoiceNumberReservationService invoiceNumberReservationService;
|
||||||
|
@Autowired
|
||||||
|
private ISecurityService securityService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Directory where payment documents are put
|
* Directory where payment documents are put
|
||||||
|
@ -73,8 +75,10 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
|
||||||
@Value("${jeecg.path.save}")
|
@Value("${jeecg.path.save}")
|
||||||
private String PAYMENT_DOC_DIR;
|
private String PAYMENT_DOC_DIR;
|
||||||
|
|
||||||
@Value("${jeecg.path.purchaseTemplatePath}")
|
@Value("${jeecg.path.purchaseTemplatePath_EU}")
|
||||||
private String INVOICE_TEMPLATE;
|
private String INVOICE_TEMPLATE_EU;
|
||||||
|
@Value("${jeecg.path.purchaseTemplatePath_US}")
|
||||||
|
private String INVOICE_TEMPLATE_US;
|
||||||
|
|
||||||
@Value("${jeecg.path.purchaseInvoiceDir}")
|
@Value("${jeecg.path.purchaseInvoiceDir}")
|
||||||
private String INVOICE_DIR;
|
private String INVOICE_DIR;
|
||||||
|
@ -403,7 +407,7 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public String addPurchase(String username, Client client, String invoiceNumber, List<SkuQuantity> skuQuantities,
|
public String addPurchase(String username, Client client, String invoiceNumber, List<SkuQuantity> skuQuantities,
|
||||||
Map<PlatformOrder, List<PlatformOrderContent>> orderAndContent) throws UserException {
|
Map<PlatformOrder, List<PlatformOrderContent>> orderAndContent, List<String> ordersWithStock) throws UserException {
|
||||||
Objects.requireNonNull(orderAndContent);
|
Objects.requireNonNull(orderAndContent);
|
||||||
|
|
||||||
List<OrderContentDetail> details = platformOrderService.searchPurchaseOrderDetail(skuQuantities);
|
List<OrderContentDetail> details = platformOrderService.searchPurchaseOrderDetail(skuQuantities);
|
||||||
|
@ -438,7 +442,15 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
|
||||||
purchaseOrderContentMapper.addAll(username, purchaseID, entries);
|
purchaseOrderContentMapper.addAll(username, purchaseID, entries);
|
||||||
|
|
||||||
// 2.1 save extra sku
|
// 2.1 save extra sku
|
||||||
skuService.addInventory(skuQuantities, orderAndContent.keySet().stream().map(PlatformOrder::getId).collect(Collectors.toList()));
|
List<String> orderIds = orderAndContent.keySet().stream()
|
||||||
|
.map(PlatformOrder::getId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if( ordersWithStock != null && !ordersWithStock.isEmpty()) {
|
||||||
|
orderIds = orderIds.stream()
|
||||||
|
.filter(orderId -> !ordersWithStock.contains(orderId))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
skuService.addInventory(skuQuantities, orderIds);
|
||||||
|
|
||||||
// 3. save the application of promotion information
|
// 3. save the application of promotion information
|
||||||
List<PromotionHistoryEntry> promotionHistoryEntries = details.stream()
|
List<PromotionHistoryEntry> promotionHistoryEntries = details.stream()
|
||||||
|
@ -459,6 +471,8 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
|
||||||
}
|
}
|
||||||
for (Map.Entry<PlatformOrder, List<PlatformOrderContent>> entry : orderAndContent.entrySet()) {
|
for (Map.Entry<PlatformOrder, List<PlatformOrderContent>> entry : orderAndContent.entrySet()) {
|
||||||
PlatformOrder platformOrder = entry.getKey();
|
PlatformOrder platformOrder = entry.getKey();
|
||||||
|
if(ordersWithStock != null && ordersWithStock.contains(platformOrder.getId()))
|
||||||
|
continue;
|
||||||
List<PlatformOrderContent> orderContents = entry.getValue();
|
List<PlatformOrderContent> orderContents = entry.getValue();
|
||||||
platformOrder.setStatus(PlatformOrder.Status.Purchasing.code);
|
platformOrder.setStatus(PlatformOrder.Status.Purchasing.code);
|
||||||
for (PlatformOrderContent orderContent : orderContents) {
|
for (PlatformOrderContent orderContent : orderContents) {
|
||||||
|
@ -533,22 +547,26 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InvoiceMetaData makeInvoice(String purchaseID) throws IOException, UserException {
|
public InvoiceMetaData makeInvoice(String purchaseID) throws IOException, UserException {
|
||||||
Client client = clientService.getCurrentClient();
|
boolean isEmployee = securityService.checkIsEmployee();
|
||||||
if(client == null) {
|
Client client;
|
||||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
if(!isEmployee) {
|
||||||
if (sysUser.getOrgCode().contains("A01") || sysUser.getOrgCode().contains("A03")) {
|
client = clientService.getCurrentClient();
|
||||||
client = clientService.getClientFromPurchase(purchaseID);
|
if (client == null)
|
||||||
}
|
|
||||||
else
|
|
||||||
throw new UserException("User is not a client");
|
throw new UserException("User is not a client");
|
||||||
}
|
} else
|
||||||
|
client = clientService.getClientFromPurchase(purchaseID);
|
||||||
List<PurchaseInvoiceEntry> purchaseOrderSkuList = purchaseOrderContentMapper.selectInvoiceDataByID(purchaseID);
|
List<PurchaseInvoiceEntry> purchaseOrderSkuList = purchaseOrderContentMapper.selectInvoiceDataByID(purchaseID);
|
||||||
List<PromotionDetail> promotionDetails = skuPromotionHistoryMapper.selectPromotionByPurchase(purchaseID);
|
List<PromotionDetail> promotionDetails = skuPromotionHistoryMapper.selectPromotionByPurchase(purchaseID);
|
||||||
String invoiceCode = purchaseOrderMapper.selectById(purchaseID).getInvoiceNumber();
|
String invoiceCode = purchaseOrderMapper.selectById(purchaseID).getInvoiceNumber();
|
||||||
BigDecimal eurToUsd = exchangeRatesMapper.getLatestExchangeRate("EUR", "USD");
|
BigDecimal eurToUsd = exchangeRatesMapper.getLatestExchangeRate("EUR", "USD");
|
||||||
|
|
||||||
String filename = "Invoice N°" + invoiceCode + " (" + client.getInvoiceEntity() + ").xlsx";
|
String filename = "Invoice N°" + invoiceCode + " (" + client.getInvoiceEntity() + ").xlsx";
|
||||||
Path template = Paths.get(INVOICE_TEMPLATE);
|
Path template;
|
||||||
|
if (client.getCurrency().equals("USD")) {
|
||||||
|
template = Paths.get(INVOICE_TEMPLATE_US);
|
||||||
|
} else {
|
||||||
|
template = Paths.get(INVOICE_TEMPLATE_EU);
|
||||||
|
}
|
||||||
Path newInvoice = Paths.get(INVOICE_DIR, filename);
|
Path newInvoice = Paths.get(INVOICE_DIR, filename);
|
||||||
Files.copy(template, newInvoice, StandardCopyOption.REPLACE_EXISTING);
|
Files.copy(template, newInvoice, StandardCopyOption.REPLACE_EXISTING);
|
||||||
PurchaseInvoice pv = new PurchaseInvoice(client, invoiceCode, "Purchase Invoice", purchaseOrderSkuList, promotionDetails, eurToUsd);
|
PurchaseInvoice pv = new PurchaseInvoice(client, invoiceCode, "Purchase Invoice", purchaseOrderSkuList, promotionDetails, eurToUsd);
|
||||||
|
@ -558,6 +576,7 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
|
||||||
@Override
|
@Override
|
||||||
public InvoiceMetaData makeInvoiceTest(int nbOfLines) throws Exception {
|
public InvoiceMetaData makeInvoiceTest(int nbOfLines) throws Exception {
|
||||||
Client client = clientService.getClientBySku("test");
|
Client client = clientService.getClientBySku("test");
|
||||||
|
client.setCurrency("USD");
|
||||||
List<PurchaseInvoiceEntry> purchaseOrderSkuList = new ArrayList<>();
|
List<PurchaseInvoiceEntry> purchaseOrderSkuList = new ArrayList<>();
|
||||||
// -5 because we have at least 5 lines of promotions
|
// -5 because we have at least 5 lines of promotions
|
||||||
for (int i = 0; i < nbOfLines - 5; i++) {
|
for (int i = 0; i < nbOfLines - 5; i++) {
|
||||||
|
@ -571,7 +590,11 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
|
||||||
BigDecimal eurToUsd = exchangeRatesMapper.getLatestExchangeRate("EUR", "USD");
|
BigDecimal eurToUsd = exchangeRatesMapper.getLatestExchangeRate("EUR", "USD");
|
||||||
|
|
||||||
String filename = "Invoice N°" + invoiceCode + " (" + client.getInvoiceEntity() + ")_" + nbOfLines + ".xlsx";
|
String filename = "Invoice N°" + invoiceCode + " (" + client.getInvoiceEntity() + ")_" + nbOfLines + ".xlsx";
|
||||||
Path template = Paths.get(INVOICE_TEMPLATE);
|
Path template;
|
||||||
|
if(client.getCurrency().equals("USD"))
|
||||||
|
template = Paths.get(INVOICE_TEMPLATE_US);
|
||||||
|
else
|
||||||
|
template = Paths.get(INVOICE_TEMPLATE_EU);
|
||||||
Path newInvoice = Paths.get(INVOICE_TEST_DIR, filename);
|
Path newInvoice = Paths.get(INVOICE_TEST_DIR, filename);
|
||||||
Files.copy(template, newInvoice, StandardCopyOption.REPLACE_EXISTING);
|
Files.copy(template, newInvoice, StandardCopyOption.REPLACE_EXISTING);
|
||||||
PurchaseInvoice pv = new PurchaseInvoice(client, invoiceCode, "Purchase Invoice", purchaseOrderSkuList, promotionDetails, eurToUsd);
|
PurchaseInvoice pv = new PurchaseInvoice(client, invoiceCode, "Purchase Invoice", purchaseOrderSkuList, promotionDetails, eurToUsd);
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package org.jeecg.modules.business.vo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ManualInvoiceOrderParam {
|
||||||
|
private final String clientID;
|
||||||
|
private final List<String> orderIds;
|
||||||
|
private final String type;
|
||||||
|
private final List<String> ordersWithStock = new ArrayList<>();
|
||||||
|
public ManualInvoiceOrderParam(@JsonProperty("clientID") String clientID, @JsonProperty("orderIds") List<String> orderIds, @JsonProperty("type") String type, @JsonProperty("ordersWithStock") List<String> ordersWithStock) {
|
||||||
|
this.clientID = clientID;
|
||||||
|
this.orderIds = orderIds;
|
||||||
|
this.type = type;
|
||||||
|
if (ordersWithStock != null) {
|
||||||
|
this.ordersWithStock.addAll(ordersWithStock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -229,7 +229,8 @@ jeecg:
|
||||||
creditInvoiceDir: /wia/invoices/credit
|
creditInvoiceDir: /wia/invoices/credit
|
||||||
|
|
||||||
# purchase invoice template
|
# purchase invoice template
|
||||||
purchaseTemplatePath: /wia/files/Purchase_Invoice_Template.xlsx
|
purchaseTemplatePath_EU: /wia/files/Purchase_Invoice_Template_EU.xlsx
|
||||||
|
purchaseTemplatePath_US: /wia/files/Purchase_Invoice_Template_US.xlsx
|
||||||
# where to store generated file
|
# where to store generated file
|
||||||
purchaseInvoiceDir: /wia/invoices/purchase
|
purchaseInvoiceDir: /wia/invoices/purchase
|
||||||
purchaseInvoiceTestDir: /wia/invoices/test/purchase
|
purchaseInvoiceTestDir: /wia/invoices/test/purchase
|
||||||
|
|
Loading…
Reference in New Issue