Merge branch 'test' into feauture-20261104

# Conflicts:
#	bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcProfitReportServiceImpl.java
This commit is contained in:
liuminghui
2026-11-05 16:38:53 +08:00
73 changed files with 5246 additions and 830 deletions
@@ -305,6 +305,14 @@ public class BillingController extends BaseController
return success(task);
}
@PreAuthorize("@ss.hasPermi('price:orderBill:rebill')")
@Log(title = "Order bill local rebill cancel", businessType = BusinessType.UPDATE)
@PostMapping("/orderBill/rebill/task/{taskId}/cancel")
public AjaxResult cancelLocalRebill(@PathVariable("taskId") String taskId)
{
return success(prcOrderBillService.cancelLocalRebill(taskId));
}
/**
* Order no options for remote-search dropdown (bill list multi search).
*/
@@ -0,0 +1,453 @@
package com.bms.web.controller.price;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.bms.price.service.support.UploadFileBatch;
import com.bms.common.annotation.Log;
import com.bms.common.core.controller.BaseController;
import com.bms.common.core.domain.AjaxResult;
import com.bms.common.core.page.TableDataInfo;
import com.bms.common.enums.BusinessType;
import com.bms.common.utils.MessageUtils;
import com.bms.common.utils.StringUtils;
import com.bms.price.domain.PrcCustomerPriceSet;
import com.bms.price.domain.PrcCustomerPriceSetBatch;
import com.bms.price.domain.PrcPriceExcelFile;
import com.bms.price.domain.PrcPriceSet;
import com.bms.price.domain.PrcPriceSetDetail;
import com.bms.price.domain.PrcPriceSetSaveTask;
import com.bms.price.domain.PrcPriceSetVersion;
import com.bms.price.service.IPrcPriceExcelFileService;
import com.bms.price.service.IPrcPriceSetService;
/**
* Exclusive quote (shares prc_price_set with PACKAGE)
*
* @author bms
*/
@RestController
@RequestMapping("/price/exclusive")
public class ExclusiveQuoteController extends BaseController
{
@Autowired
private IPrcPriceSetService priceSetService;
@Autowired
private IPrcPriceExcelFileService priceExcelFileService;
@PreAuthorize("@ss.hasPermi('price:exclusive:list')")
@GetMapping("/list")
public TableDataInfo list(PrcPriceSet set)
{
set.setSetCategory(PrcPriceSet.CATEGORY_EXCLUSIVE);
startPage();
List<PrcPriceSet> list = priceSetService.selectPrcPriceSetList(set);
return getDataTable(list);
}
@PreAuthorize("@ss.hasPermi('price:exclusive:query')")
@GetMapping("/{priceSetId:[0-9]+}")
public AjaxResult getInfo(@PathVariable Long priceSetId)
{
priceSetService.assertSetCategory(priceSetId, PrcPriceSet.CATEGORY_EXCLUSIVE);
return success(priceSetService.selectPrcPriceSetById(priceSetId));
}
@PreAuthorize("@ss.hasPermi('price:exclusive:add')")
@Log(title = "Exclusive quote", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody PrcPriceSet set)
{
if (set.getPriceSetId() != null)
{
priceSetService.assertSetCategory(set.getPriceSetId(), PrcPriceSet.CATEGORY_EXCLUSIVE);
}
set.setSetCategory(PrcPriceSet.CATEGORY_EXCLUSIVE);
set.setCreateBy(getUsername());
set.setUpdateBy(getUsername());
String taskId = priceSetService.submitSaveAsync(set);
// Do not pass bare String to success(): overload puts it into msg, not data.
Map<String, Object> payload = new HashMap<String, Object>();
payload.put("taskId", taskId);
return success(payload);
}
@PreAuthorize("@ss.hasPermi('price:exclusive:query')")
@GetMapping("/save/task/{taskId}")
public AjaxResult getSaveTask(@PathVariable String taskId)
{
PrcPriceSetSaveTask task = priceSetService.getSaveTask(taskId);
if (task == null)
{
return error(MessageUtils.message("price.set.save.task.notExists"));
}
return success(task);
}
@PreAuthorize("@ss.hasPermi('price:exclusive:edit')")
@Log(title = "Exclusive quote", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody PrcPriceSet set)
{
priceSetService.assertSetCategory(set.getPriceSetId(), PrcPriceSet.CATEGORY_EXCLUSIVE);
set.setSetCategory(PrcPriceSet.CATEGORY_EXCLUSIVE);
set.setUpdateBy(getUsername());
return toAjax(priceSetService.updatePrcPriceSet(set));
}
/** Update package name and note only. */
@PreAuthorize("@ss.hasPermi('price:exclusive:edit')")
@Log(title = "Exclusive quote basic", businessType = BusinessType.UPDATE)
@PutMapping("/basic")
public AjaxResult editBasic(@RequestBody PrcPriceSet set)
{
priceSetService.assertSetCategory(set.getPriceSetId(), PrcPriceSet.CATEGORY_EXCLUSIVE);
set.setUpdateBy(getUsername());
return toAjax(priceSetService.updateBasicInfo(set));
}
@PreAuthorize("@ss.hasPermi('price:exclusive:remove')")
@Log(title = "Exclusive quote", businessType = BusinessType.DELETE)
@DeleteMapping("/{priceSetIds}")
public AjaxResult remove(@PathVariable Long[] priceSetIds)
{
if (priceSetIds != null)
{
for (Long id : priceSetIds)
{
priceSetService.assertSetCategory(id, PrcPriceSet.CATEGORY_EXCLUSIVE);
}
}
return toAjax(priceSetService.deletePrcPriceSetByIds(priceSetIds));
}
@PreAuthorize("@ss.hasPermi('price:exclusive:audit')")
@Log(title = "Exclusive quote提交审核", businessType = BusinessType.UPDATE)
@PutMapping("/submit/{priceSetId}")
public AjaxResult submit(@PathVariable Long priceSetId)
{
priceSetService.assertSetCategory(priceSetId, PrcPriceSet.CATEGORY_EXCLUSIVE);
return toAjax(priceSetService.submit(priceSetId, getUsername()));
}
@PreAuthorize("@ss.hasPermi('price:exclusive:audit')")
@Log(title = "Exclusive quote生效", businessType = BusinessType.UPDATE)
@PutMapping("/approve/{priceSetId}")
public AjaxResult approve(@PathVariable Long priceSetId)
{
priceSetService.assertSetCategory(priceSetId, PrcPriceSet.CATEGORY_EXCLUSIVE);
return toAjax(priceSetService.approve(priceSetId, getUsername()));
}
@PreAuthorize("@ss.hasPermi('price:exclusive:audit')")
@Log(title = "Exclusive quote驳回", businessType = BusinessType.UPDATE)
@PutMapping("/reject/{priceSetId}")
public AjaxResult reject(@PathVariable Long priceSetId)
{
priceSetService.assertSetCategory(priceSetId, PrcPriceSet.CATEGORY_EXCLUSIVE);
return toAjax(priceSetService.reject(priceSetId, getUsername()));
}
@PreAuthorize("@ss.hasPermi('price:exclusive:edit')")
@Log(title = "Exclusive quote version activate", businessType = BusinessType.UPDATE)
@PutMapping("/version/activate/{psvId}")
public AjaxResult activateVersion(@PathVariable Long psvId, @RequestBody(required = false) PrcPriceSetVersion body)
{
Date effectiveTime = body == null ? null : body.getEffectiveTime();
return toAjax(priceSetService.activateVersion(psvId, effectiveTime, getUsername()));
}
@PreAuthorize("@ss.hasPermi('price:exclusive:add')")
@Log(title = "Exclusive quote version copy", businessType = BusinessType.INSERT)
@PostMapping("/version/copy/{psvId}")
public AjaxResult copyVersion(@PathVariable Long psvId)
{
Long newPsvId = priceSetService.copyVersion(psvId, getUsername());
return success(newPsvId);
}
@PreAuthorize("@ss.hasPermi('price:exclusive:add')")
@Log(title = "Exclusive quote version create", businessType = BusinessType.INSERT)
@PostMapping("/version/create/{priceSetId}")
public AjaxResult createVersion(@PathVariable Long priceSetId)
{
priceSetService.assertSetCategory(priceSetId, PrcPriceSet.CATEGORY_EXCLUSIVE);
Long newPsvId = priceSetService.createVersion(priceSetId, getUsername());
return success(newPsvId);
}
@PreAuthorize("@ss.hasPermi('price:exclusive:edit')")
@Log(title = "Exclusive quote version delete", businessType = BusinessType.DELETE)
@DeleteMapping("/version/{psvId}")
public AjaxResult deleteVersion(@PathVariable Long psvId)
{
return toAjax(priceSetService.deleteVersion(psvId, getUsername()));
}
/** Import excel attachments for a version (prc_price_excel_file.psv_id). */
@PreAuthorize("@ss.hasPermi('price:exclusive:list')")
@GetMapping("/version/{psvId}/excelFiles")
public AjaxResult versionExcelFiles(@PathVariable Long psvId)
{
List<PrcPriceExcelFile> list = priceExcelFileService.selectByPsvId(psvId);
return success(list);
}
@PreAuthorize("@ss.hasPermi('price:exclusive:audit')")
@Log(title = "Exclusive quote disable", businessType = BusinessType.UPDATE)
@PutMapping("/disable/{priceSetId}")
public AjaxResult disable(@PathVariable Long priceSetId)
{
priceSetService.assertSetCategory(priceSetId, PrcPriceSet.CATEGORY_EXCLUSIVE);
return toAjax(priceSetService.disable(priceSetId, getUsername()));
}
@PreAuthorize("@ss.hasPermi('price:exclusive:audit')")
@Log(title = "Exclusive quote enable", businessType = BusinessType.UPDATE)
@PutMapping("/enable/{priceSetId}")
public AjaxResult enable(@PathVariable Long priceSetId)
{
priceSetService.assertSetCategory(priceSetId, PrcPriceSet.CATEGORY_EXCLUSIVE);
return toAjax(priceSetService.enable(priceSetId, getUsername()));
}
@PreAuthorize("@ss.hasPermi('price:exclusive:add')")
@Log(title = "Exclusive quote copy", businessType = BusinessType.INSERT)
@PostMapping("/copy/{priceSetId}")
public AjaxResult copy(@PathVariable Long priceSetId)
{
priceSetService.assertSetCategory(priceSetId, PrcPriceSet.CATEGORY_EXCLUSIVE);
Long id = priceSetService.copy(priceSetId, getUsername());
return success(id);
}
@PreAuthorize("@ss.hasPermi('price:exclusive:query')")
@PostMapping("/validate")
public AjaxResult validate(@RequestBody PrcPriceSet set)
{
return success(priceSetService.validate(set));
}
@PreAuthorize("@ss.hasPermi('price:exclusive:list')")
@GetMapping("/detail/list")
public TableDataInfo detailList(PrcPriceSetDetail detail)
{
startPage();
List<PrcPriceSetDetail> list = priceSetService.selectDetailList(detail);
return getDataTable(list);
}
/** All detail rows for one product (no page); used by edit-price drawer. */
@PreAuthorize("@ss.hasPermi('price:exclusive:list')")
@GetMapping("/detail/byProduct")
public AjaxResult detailByProduct(@RequestParam("psvId") Long psvId,
@RequestParam("productCode") String productCode)
{
return success(priceSetService.selectDetailListByProduct(psvId, productCode));
}
/** All detail rows for a version (no page); batch prefetch instead of N byProduct calls. */
@PreAuthorize("@ss.hasPermi('price:exclusive:list')")
@GetMapping("/detail/byVersion")
public AjaxResult detailByVersion(@RequestParam("psvId") Long psvId)
{
return success(priceSetService.selectDetailListByVersion(psvId));
}
/**
* 版本明细搜索下拉选项:按版本去重后的 产品/国家/分区
*/
@PreAuthorize("@ss.hasPermi('price:exclusive:list')")
@GetMapping("/detail/options")
public AjaxResult detailOptions(@RequestParam("psvId") Long psvId)
{
return success(priceSetService.selectDetailOptions(psvId));
}
@PreAuthorize("@ss.hasPermi('price:exclusive:edit') or @ss.hasPermi('price:exclusive:forceEdit')")
@Log(title = "Exclusive quote明细", businessType = BusinessType.INSERT)
@PostMapping("/detail")
public AjaxResult addDetail(@RequestBody PrcPriceSetDetail detail)
{
return toAjax(priceSetService.insertDetail(detail));
}
@PreAuthorize("@ss.hasPermi('price:exclusive:edit') or @ss.hasPermi('price:exclusive:forceEdit')")
@Log(title = "Exclusive quote明细", businessType = BusinessType.UPDATE)
@PutMapping("/detail")
public AjaxResult editDetail(@RequestBody PrcPriceSetDetail detail)
{
return toAjax(priceSetService.updateDetail(detail));
}
@PreAuthorize("@ss.hasPermi('price:exclusive:edit') or @ss.hasPermi('price:exclusive:forceEdit')")
@Log(title = "Exclusive quote价格导入", businessType = BusinessType.IMPORT)
@PostMapping("/detail/importPrices")
public AjaxResult importDetailPrices(
@RequestParam(value = "files", required = false) MultipartFile[] files,
@RequestParam(value = "file", required = false) MultipartFile file,
@RequestParam("priceSetId") Long priceSetId,
@RequestParam(value = "psvId", required = false) Long psvId,
@RequestParam(value = "updateOnly", required = false, defaultValue = "false") boolean updateOnly,
@RequestParam(value = "replaceByProductCountry", required = false, defaultValue = "false") boolean replaceByProductCountry,
@RequestParam(value = "countryCode", required = false) String countryCode)
throws Exception
{
priceSetService.assertSetCategory(priceSetId, PrcPriceSet.CATEGORY_EXCLUSIVE);
String taskId = priceSetService.submitImportDetailPricesAsync(priceSetId, psvId, UploadFileBatch.collect(files, file),
getUsername(), updateOnly, replaceByProductCountry, countryCode);
Map<String, Object> payload = new HashMap<String, Object>();
payload.put("taskId", taskId);
return success(payload);
}
/**
* Preview pull product library (no DB write). For create wizard before finish.
*/
@PreAuthorize("@ss.hasPermi('price:exclusive:edit') or @ss.hasPermi('price:exclusive:forceEdit') or @ss.hasPermi('price:exclusive:add')")
@PostMapping("/detail/previewPullFromLibrary")
public AjaxResult previewPullFromLibrary()
{
return success(priceSetService.previewPullFromLibrary());
}
/**
* Preview Excel import (no DB write). Optional detailsJson for updateOnly / build-price merge.
* Optional countryCode = single-country dedicated-line Excel (same as product country import).
*/
@PreAuthorize("@ss.hasPermi('price:exclusive:edit') or @ss.hasPermi('price:exclusive:forceEdit') or @ss.hasPermi('price:exclusive:add')")
@PostMapping("/detail/previewImportPrices")
public AjaxResult previewImportPrices(
@RequestParam(value = "files", required = false) MultipartFile[] files,
@RequestParam(value = "file", required = false) MultipartFile file,
@RequestParam(value = "updateOnly", required = false, defaultValue = "false") boolean updateOnly,
@RequestParam(value = "replaceByProductCountry", required = false, defaultValue = "false") boolean replaceByProductCountry,
@RequestParam(value = "countryCode", required = false) String countryCode,
@RequestParam(value = "detailsJson", required = false) String detailsJson) throws Exception
{
java.util.List<MultipartFile> batch = UploadFileBatch.collect(files, file);
java.util.List<byte[]> bytesList = new java.util.ArrayList<byte[]>();
java.util.List<String> names = new java.util.ArrayList<String>();
for (MultipartFile item : batch)
{
bytesList.add(item.getBytes());
names.add(item.getOriginalFilename());
}
List<PrcPriceSetDetail> existing = null;
if (StringUtils.isNotEmpty(detailsJson))
{
existing = com.alibaba.fastjson2.JSON.parseArray(detailsJson, PrcPriceSetDetail.class);
}
return success(priceSetService.previewImportDetailPricesMany(
bytesList, names, updateOnly, existing, replaceByProductCountry, countryCode, true));
}
/**
* Async pull product library into version details. Returns taskId; poll /save/task/{taskId}.
*/
@PreAuthorize("@ss.hasPermi('price:exclusive:edit') or @ss.hasPermi('price:exclusive:forceEdit')")
@Log(title = "Exclusive quote拉取产品", businessType = BusinessType.IMPORT)
@PostMapping("/detail/pullFromLibrary")
public AjaxResult pullFromLibrary(@RequestParam("priceSetId") Long priceSetId,
@RequestParam(value = "psvId", required = false) Long psvId,
@RequestParam(value = "force", required = false, defaultValue = "false") boolean force)
{
priceSetService.assertSetCategory(priceSetId, PrcPriceSet.CATEGORY_EXCLUSIVE);
String taskId = priceSetService.submitPullFromLibraryAsync(priceSetId, psvId, force, getUsername());
Map<String, Object> payload = new HashMap<String, Object>();
payload.put("taskId", taskId);
return success(payload);
}
/**
* Async batch write of detail surcharge snapshots. Returns taskId; poll /save/task/{taskId}.
*/
@PreAuthorize("@ss.hasPermi('price:exclusive:edit') or @ss.hasPermi('price:exclusive:forceEdit')")
@Log(title = "Exclusive quote附加费", businessType = BusinessType.UPDATE)
@PostMapping("/detail/surcharge/async")
public AjaxResult batchSurchargeAsync(@RequestBody List<PrcPriceSetDetail> details)
{
String taskId = priceSetService.submitDetailSurchargeAsync(details);
Map<String, Object> payload = new HashMap<String, Object>();
payload.put("taskId", taskId);
return success(payload);
}
@PreAuthorize("@ss.hasPermi('price:exclusive:edit') or @ss.hasPermi('price:exclusive:forceEdit')")
@Log(title = "Exclusive quote明细", businessType = BusinessType.DELETE)
@DeleteMapping("/detail/{psdIds}")
public AjaxResult removeDetail(@PathVariable Long[] psdIds)
{
return toAjax(priceSetService.deleteDetailByIds(psdIds));
}
@PreAuthorize("@ss.hasPermi('price:exclusive:list')")
@GetMapping("/customer/list")
public TableDataInfo customerList(PrcCustomerPriceSet customer)
{
startPage();
List<PrcCustomerPriceSet> list = priceSetService.selectCustomerList(customer);
return getDataTable(list);
}
@PreAuthorize("@ss.hasPermi('price:exclusive:edit')")
@Log(title = "Exclusive quote客户绑定", businessType = BusinessType.INSERT)
@PostMapping("/customer")
public AjaxResult addCustomer(@RequestBody PrcCustomerPriceSet customer)
{
if (customer != null && customer.getPriceSetId() != null)
{
priceSetService.assertSetCategory(customer.getPriceSetId(), PrcPriceSet.CATEGORY_EXCLUSIVE);
}
customer.setCreateBy(getUsername());
return toAjax(priceSetService.insertCustomer(customer));
}
@PreAuthorize("@ss.hasPermi('price:exclusive:edit')")
@Log(title = "Exclusive quote客户批量绑定", businessType = BusinessType.INSERT)
@PostMapping("/customer/batch")
public AjaxResult batchAddCustomer(@RequestBody PrcCustomerPriceSetBatch batch)
{
if (batch != null && batch.getPriceSetId() != null)
{
priceSetService.assertSetCategory(batch.getPriceSetId(), PrcPriceSet.CATEGORY_EXCLUSIVE);
}
batch.setCreateBy(getUsername());
batch.setUpdateBy(getUsername());
return success(priceSetService.batchInsertCustomers(batch));
}
@PreAuthorize("@ss.hasPermi('price:exclusive:edit')")
@Log(title = "Exclusive quote客户绑定", businessType = BusinessType.UPDATE)
@PutMapping("/customer")
public AjaxResult editCustomer(@RequestBody PrcCustomerPriceSet customer)
{
customer.setUpdateBy(getUsername());
return toAjax(priceSetService.updateCustomer(customer));
}
@PreAuthorize("@ss.hasPermi('price:exclusive:edit')")
@Log(title = "Exclusive quote客户绑定", businessType = BusinessType.DELETE)
@DeleteMapping("/customer/{customerPricesetIds}")
public AjaxResult removeCustomer(@PathVariable Long[] customerPricesetIds)
{
return toAjax(priceSetService.deleteCustomerByIds(customerPricesetIds));
}
}
@@ -55,6 +55,8 @@ public class PriceSetController extends BaseController
@GetMapping("/list")
public TableDataInfo list(PrcPriceSet set)
{
// Ordinary package module: never mix exclusive quotes into this list.
set.setSetCategory(PrcPriceSet.CATEGORY_PACKAGE);
startPage();
List<PrcPriceSet> list = priceSetService.selectPrcPriceSetList(set);
return getDataTable(list);
@@ -64,6 +66,7 @@ public class PriceSetController extends BaseController
@GetMapping("/{priceSetId:[0-9]+}")
public AjaxResult getInfo(@PathVariable Long priceSetId)
{
priceSetService.assertSetCategory(priceSetId, PrcPriceSet.CATEGORY_PACKAGE);
return success(priceSetService.selectPrcPriceSetById(priceSetId));
}
@@ -72,6 +75,11 @@ public class PriceSetController extends BaseController
@PostMapping
public AjaxResult add(@Validated @RequestBody PrcPriceSet set)
{
if (set.getPriceSetId() != null)
{
priceSetService.assertSetCategory(set.getPriceSetId(), PrcPriceSet.CATEGORY_PACKAGE);
}
set.setSetCategory(PrcPriceSet.CATEGORY_PACKAGE);
set.setCreateBy(getUsername());
set.setUpdateBy(getUsername());
String taskId = priceSetService.submitSaveAsync(set);
@@ -98,6 +106,8 @@ public class PriceSetController extends BaseController
@PutMapping
public AjaxResult edit(@Validated @RequestBody PrcPriceSet set)
{
priceSetService.assertSetCategory(set.getPriceSetId(), PrcPriceSet.CATEGORY_PACKAGE);
set.setSetCategory(PrcPriceSet.CATEGORY_PACKAGE);
set.setUpdateBy(getUsername());
return toAjax(priceSetService.updatePrcPriceSet(set));
}
@@ -108,6 +118,7 @@ public class PriceSetController extends BaseController
@PutMapping("/basic")
public AjaxResult editBasic(@RequestBody PrcPriceSet set)
{
priceSetService.assertSetCategory(set.getPriceSetId(), PrcPriceSet.CATEGORY_PACKAGE);
set.setUpdateBy(getUsername());
return toAjax(priceSetService.updateBasicInfo(set));
}
@@ -32,6 +32,7 @@ import com.bms.common.utils.uuid.IdUtils;
import com.bms.common.utils.poi.ExcelUtil;
// 提成功能暂停使用:import com.bms.price.domain.PrcProfitCommissionRate;
import com.bms.price.domain.PrcProfitReportExport;
import com.bms.price.enums.ProfitAreaRule;
import com.bms.price.domain.vo.PrcProfitReportOrderRow;
import com.bms.price.domain.vo.PrcProfitReportProductRow;
import com.bms.price.domain.vo.PrcProfitReportQuery;
@@ -58,6 +59,14 @@ public class PrcProfitReportController extends BaseController
return getDataTable(profitReportService.selectCustomerOptions(keywords));
}
/** 客户区域字典值与毛利规则的映射。 */
@PreAuthorize("@ss.hasPermi('report:profit:list')")
@GetMapping("/area-rules")
public AjaxResult areaRules()
{
return success(profitReportService.selectAreaRules());
}
@PreAuthorize("@ss.hasPermi('report:profit:list')")
@GetMapping("/summary")
public AjaxResult summary(PrcProfitReportQuery query)
@@ -118,7 +127,7 @@ public class PrcProfitReportController extends BaseController
try
{
List<PrcProfitReportOrderRow> rows = profitReportService.selectOrderRows(query);
return finishExport(export, rows, PrcProfitReportOrderRow.class, "订单毛利报表");
return finishExport(export, rows, PrcProfitReportOrderRow.class, "订单毛利报表", query.getProfitRule());
}
catch (RuntimeException e)
{
@@ -136,7 +145,7 @@ public class PrcProfitReportController extends BaseController
try
{
List<PrcProfitReportProductRow> rows = profitReportService.selectProductRows(query);
return finishExport(export, rows, PrcProfitReportProductRow.class, "产品毛利报表");
return finishExport(export, rows, PrcProfitReportProductRow.class, "产品毛利报表", query.getProfitRule());
}
catch (RuntimeException e)
{
@@ -200,7 +209,8 @@ public class PrcProfitReportController extends BaseController
return export;
}
private <T> AjaxResult finishExport(PrcProfitReportExport export, List<T> rows, Class<T> rowType, String sheetName)
private <T> AjaxResult finishExport(PrcProfitReportExport export, List<T> rows, Class<T> rowType, String sheetName,
String profitRule)
{
Path temp = null;
try
@@ -208,7 +218,12 @@ public class PrcProfitReportController extends BaseController
temp = Files.createTempFile("profit-report-", ".xlsx");
try (OutputStream output = Files.newOutputStream(temp))
{
new ExcelUtil<T>(rowType).exportExcelToStream(rows, sheetName, output);
ExcelUtil<T> excelUtil = new ExcelUtil<>(rowType);
if (ProfitAreaRule.GUANGZHOU.name().equals(profitRule))
{
excelUtil.hideColumn("costAmount", "redlineGrossProfit", "redlineGrossMarginRate");
}
excelUtil.exportExcelToStream(rows, sheetName, output);
}
String objectKey = "report/profit/" + DateUtils.datePath() + "/" + IdUtils.fastSimpleUUID() + ".xlsx";
export.setStorageKey(ossStorage.upload(temp, objectKey,
@@ -224,6 +224,11 @@ price.bill.billingFail.weight=计费失败:销售价未匹配重量段
price.bill.billingFail.catalogProduct=计费失败:产品价未匹配产品
price.bill.billingFail.catalogCountry=计费失败:产品价未匹配国家
price.bill.billingFail.catalogWeight=计费失败:产品价未匹配重量段
price.bill.billingFail.packageNotEnabled=计费失败:套餐未启用
price.bill.billingFail.noActivePackageVersion=计费失败:计费日无生效套餐版本
price.bill.billingFail.noCustomerPackage=计费失败:客户未绑定套餐
price.bill.packageNotEnabled=客户已绑定套餐但套餐未启用,无法计费
price.quote.packageNotEnabled=客户已绑定套餐但套餐未启用,无法试算
price.bill.export.filterRequired=请先设置列表查询条件后再导出
price.bill.export.taskNotExists=导出任务不存在或已过期
price.bill.export.tooMany=匹配订单超过上限 {0} 条,请缩小筛选范围
@@ -232,3 +237,6 @@ price.bill.export.notReady=导出文件尚未生成或已失败
price.bill.export.fileMissing=导出文件不存在或路径非法
price.set.customer.batch.empty=请选择要绑定的客户
price.set.customer.batch.done=批量绑定完成:共 {0} 个客户,新绑定 {1} 个,更换 {2} 个,跳过 {3} 个
price.bill.recalc.taskCancelled=本地重新计费已取消
price.bill.recalc.taskCancelNotRunning=任务已结束或不存在,无法取消
price.bill.recalc.taskIdRequired=任务ID不能为空
@@ -0,0 +1,53 @@
package com.bms.report;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.lang.reflect.Proxy;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicInteger;
import com.bms.common.exception.ServiceException;
import com.bms.price.domain.vo.PrcProfitReportQuery;
import com.bms.price.mapper.PrcProfitReportMapper;
import com.bms.price.service.impl.PrcProfitReportServiceImpl;
import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;
class ProfitAreaRuleTest
{
@Test
void reportQueriesResolveRuleOnServerAndRejectUnknownAreas()
{
AtomicInteger calls = new AtomicInteger();
PrcProfitReportMapper mapper = (PrcProfitReportMapper) Proxy.newProxyInstance(
getClass().getClassLoader(), new Class<?>[] { PrcProfitReportMapper.class },
(proxy, method, args) -> {
calls.incrementAndGet();
return Collections.emptyList();
});
PrcProfitReportServiceImpl service = new PrcProfitReportServiceImpl();
ReflectionTestUtils.setField(service, "profitReportMapper", mapper);
PrcProfitReportQuery query = new PrcProfitReportQuery();
query.setCustomerArea(" GZ ");
query.setProfitRule("SHENZHEN");
service.selectSummary(query);
assertEquals("GZ", query.getCustomerArea());
assertEquals("GUANGZHOU", query.getProfitRule());
query.setCustomerArea("C");
query.setProfitRule("GUANGZHOU");
service.selectOrderRows(query);
assertEquals("SHENZHEN", query.getProfitRule());
service.selectProductRows(query);
assertEquals(3, calls.get());
query.setCustomerArea("UNKNOWN");
assertThrows(ServiceException.class, () -> service.selectProductRows(query));
query.setCustomerArea("");
assertThrows(ServiceException.class, () -> service.selectSummary(query));
assertEquals(3, calls.get());
assertEquals("SHENZHEN", service.selectAreaRules().get("C"));
assertEquals("GUANGZHOU", service.selectAreaRules().get("GZ"));
}
}