feat: client sku purchase access, purchase invoice USD fix, complete invoice bypass stock

pull/8523/head
Gauthier LO 2025-06-09 12:07:28 +02:00
parent 4926576b70
commit b07318a891
19 changed files with 281 additions and 130 deletions

View File

@ -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")) {

View File

@ -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 {

View File

@ -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,20 +269,29 @@ 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<SkuQuantity> skuQuantities = platformOrderContentService.searchOrderContent(orderIds); List<PurchaseInvoiceEntry> purchaseOrderSkuList = new ArrayList<>();
List<PromotionDetail> promotionDetails = new ArrayList<>();
String purchaseID = purchaseOrderService.addPurchase(username, client, invoiceCode, skuQuantities, orderAndContent); List<String> clientsThatByPassStock = clientService.getClientsByCode(CLIENT_STOCK_BYPASS_LIST);
if(clientsThatByPassStock.contains(customerId) && ordersWithStock != null && !ordersWithStock.isEmpty()) {
List<PurchaseInvoiceEntry> purchaseOrderSkuList = purchaseOrderContentMapper.selectInvoiceDataByID(purchaseID); orderIds = orderIds.stream().filter(orderId -> !ordersWithStock.contains(orderId)).collect(toList());
List<PromotionDetail> promotionDetails = skuPromotionHistoryMapper.selectPromotionByPurchase(purchaseID);
if (savRefunds != null) {
updateSavRefundsInDb(savRefunds, invoiceCode);
} }
if(extraFees != null && !extraFees.isEmpty()) { if(!orderIds.isEmpty()){
List<String> extraFeesIds = extraFees.stream().map(ExtraFeeResult::getId).collect(toList()); List<SkuQuantity> skuQuantities = platformOrderContentService.searchOrderContent(orderIds);
extraFeeService.updateInvoiceNumberByIds(extraFeesIds, invoiceCode);
String purchaseID = purchaseOrderService.addPurchase(username, client, invoiceCode, skuQuantities, orderAndContent, ordersWithStock);
purchaseOrderSkuList = purchaseOrderContentMapper.selectInvoiceDataByID(purchaseID);
promotionDetails = skuPromotionHistoryMapper.selectPromotionByPurchase(purchaseID);
if (savRefunds != null) {
updateSavRefundsInDb(savRefunds, invoiceCode);
}
if(extraFees != null && !extraFees.isEmpty()) {
List<String> extraFeesIds = extraFees.stream().map(ExtraFeeResult::getId).collect(toList());
extraFeeService.updateInvoiceNumberByIds(extraFeesIds, invoiceCode);
}
} }
updateOrdersAndContentsInDb(orderAndContent); updateOrdersAndContentsInDb(orderAndContent);
@ -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);

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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>

View File

@ -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 *
FROM client_sku
WHERE
client_id = #{mainId} </select>
<select id="getUnpairedSkus" resultType="org.jeecg.modules.business.entity.Sku"> <select id="selectByMainId" parameterType="java.lang.String" resultType="org.jeecg.modules.business.entity.ClientSku">
SELECT s.* SELECT *
FROM sku s FROM client_sku
LEFT JOIN client_sku cs ON s.id = cs.sku_id WHERE
WHERE cs.sku_id IS NULL; client_id = #{mainId} </select>
</select>
<select id="getUnpairedSkus" resultType="org.jeecg.modules.business.entity.Sku">
SELECT s.*
FROM sku s
LEFT JOIN client_sku cs ON s.id = cs.sku_id
WHERE cs.sku_id IS NULL;
</select>
<select id="getClientIdFromSkuId" resultType="java.lang.String">
SELECT client_id
FROM client_sku
WHERE sku_id = #{skuId}
</select>
</mapper> </mapper>

View File

@ -184,10 +184,18 @@
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 &gt;= '2025-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 (
SELECT id FROM currency WHERE code = 'RMB'
) )
SELECT s.id, SELECT s.id,
s.erp_code, s.erp_code,
@ -196,31 +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.price_rmb IS NULL, sp.price, IF(sp.currency_id = (SELECT id FROM rmb_id),
( (
ROUND( ROUND(
sp.price_rmb / 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
) as sku_price, ) as sku_price,
sp.threshold as discount_moq, sp.threshold as discount_moq,
IF(sp.price_rmb IS NULL, sp.discounted_price, IF(sp.currency_id = (SELECT id FROM rmb_id),
( (
ROUND( ROUND(
sp.discounted_price_rmb / 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
) 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,
@ -337,6 +339,13 @@
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 (
SELECT id FROM currency WHERE code = 'RMB'
) )
SELECT s.id, SELECT s.id,
s.erp_code, s.erp_code,
@ -345,31 +354,25 @@
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.price_rmb IS NULL, sp.price, IF(sp.currency_id = (SELECT id FROM rmb_id),
( (
ROUND( ROUND(
sp.price_rmb / 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
) as sku_price, ) as sku_price,
sp.threshold as discount_moq, sp.threshold as discount_moq,
IF(sp.price_rmb IS NULL, sp.discounted_price, IF(sp.currency_id = (SELECT id FROM rmb_id),
( (
ROUND( ROUND(
sp.discounted_price_rmb / 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
) 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,
@ -418,6 +421,9 @@
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
),
rmb_id AS (
SELECT id FROM currency WHERE code = 'RMB'
) )
SELECT s.id, SELECT s.id,
s.erp_code, s.erp_code,
@ -429,28 +435,30 @@
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.price_rmb IS NULL, sp.price, IF(sp.currency_id = (SELECT id FROM rmb_id),
( (
ROUND( ROUND(
sp.price_rmb / sp.price /
(SELECT rate (SELECT rate
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
) as sku_price, ) as sku_price,
sp.threshold as discount_moq, sp.threshold as discount_moq,
IF(sp.price_rmb IS NULL, sp.discounted_price, IF(sp.currency_id = (SELECT id FROM rmb_id),
( (
ROUND( ROUND(
sp.discounted_price_rmb / sp.discounted_price /
(SELECT rate (SELECT rate
FROM exchange_rates FROM exchange_rates
WHERE target_currency = 'EUR' AND original_currency = 'RMB' WHERE target_currency = 'EUR' AND original_currency = 'RMB'
ORDER BY create_time DESC LIMIT 1) ORDER BY create_time DESC LIMIT 1)
,2) ,2
) )
), 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,
@ -464,10 +472,7 @@
LEFT JOIN qtyInOrdersNotShippedCTE ON s.id = qtyInOrdersNotShippedCTE.ID LEFT JOIN qtyInOrdersNotShippedCTE ON s.id = qtyInOrdersNotShippedCTE.ID
WHERE client_sku.client_id = #{clientId} WHERE client_sku.client_id = #{clientId}
AND s.status = 3 AND s.status = 3
AND ( AND sp.price IS NOT NULL AND sp.price &lt;&gt; 0
(sp.price_rmb IS NOT NULL AND sp.price_rmb &lt;&gt; 0)
OR (sp.price IS NOT NULL AND sp.price &lt;&gt; 0)
)
ORDER BY s.erp_code ORDER BY s.erp_code
; ;
</select> </select>

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);
}
} }

View File

@ -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);
}
} }

View File

@ -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) {
log.error("Purchase order {} for invoice {} is already ordered, cannot be cancelled", id, invoiceNumber); if (!isEmployee && purchase.isOrdered()) {
return false; log.error("Purchase order {} for invoice {} is already ordered, cannot be cancelled", id, invoiceNumber);
return false;
}
if (purchase.getInventoryDocumentString() != null && !purchase.getInventoryDocumentString().isEmpty())
shippingInvoiceService.deleteAttachmentFile(purchase.getInventoryDocumentString());
if (purchase.getPaymentDocumentString() != null && !purchase.getPaymentDocumentString().isEmpty())
shippingInvoiceService.deleteAttachmentFile(purchase.getPaymentDocumentString());
purchaseOrderService.cancelInvoice(purchase.getId());
} else {
log.info("Purchase order not found for invoice : {}", invoiceNumber);
} }
if(purchase.getInventoryDocumentString() != null && !purchase.getInventoryDocumentString().isEmpty())
shippingInvoiceService.deleteAttachmentFile(purchase.getInventoryDocumentString());
if(purchase.getPaymentDocumentString() != null && !purchase.getPaymentDocumentString().isEmpty())
shippingInvoiceService.deleteAttachmentFile(purchase.getPaymentDocumentString());
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())) {

View File

@ -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,9 @@ 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;
// TODO : what to do with order status ????????
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 +548,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 +577,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 +591,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);

View File

@ -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);
}
}
}

View File

@ -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