增加专属报价功能
This commit is contained in:
+453
@@ -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));
|
||||
}
|
||||
|
||||
@@ -15,12 +15,19 @@ public class PrcPriceSet extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Ordinary package (default). */
|
||||
public static final String CATEGORY_PACKAGE = "PACKAGE";
|
||||
/** Boss exclusive quote. */
|
||||
public static final String CATEGORY_EXCLUSIVE = "EXCLUSIVE";
|
||||
|
||||
private Long priceSetId;
|
||||
private String priceSetCode;
|
||||
private String priceSetName;
|
||||
private String priceSetNote;
|
||||
/** FIXED / DISCOUNT */
|
||||
private String setType;
|
||||
/** PACKAGE=ordinary set / EXCLUSIVE=boss exclusive quote */
|
||||
private String setCategory;
|
||||
private BigDecimal defaultDiscount;
|
||||
private String defaultType;
|
||||
private String calculateSign;
|
||||
|
||||
@@ -59,10 +59,6 @@ public interface IBmsProductService
|
||||
|
||||
public java.util.Map<String, List<BmsProductCountry>> parseQuoteExcelByProduct(byte[] bytes, String filename) throws Exception;
|
||||
|
||||
/**
|
||||
* Parse single-country dedicated-line quote Excel (same format as product country import).
|
||||
* All weight rows are stamped with the selected country. Keys are upper-case product codes.
|
||||
*/
|
||||
public java.util.Map<String, List<BmsProductCountry>> parseCountryQuoteExcelByProduct(byte[] bytes, String filename,
|
||||
String countryCode) throws Exception;
|
||||
|
||||
|
||||
@@ -22,6 +22,9 @@ public interface IPrcPriceSetService
|
||||
|
||||
public List<PrcPriceSet> selectPrcPriceSetList(PrcPriceSet set);
|
||||
|
||||
/** Fail if the package is not in the expected category (PACKAGE / EXCLUSIVE). */
|
||||
public void assertSetCategory(Long priceSetId, String expectedCategory);
|
||||
|
||||
public Long savePrcPriceSet(PrcPriceSet set);
|
||||
|
||||
public int updatePrcPriceSet(PrcPriceSet set);
|
||||
@@ -149,6 +152,13 @@ public interface IPrcPriceSetService
|
||||
boolean updateOnly, List<PrcPriceSetDetail> existingDetails, boolean replaceByProductCountry, String countryCode)
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* @param exclusiveTemplate true = HALARA large-customer exclusive quote Excel (destination / handling fee)
|
||||
*/
|
||||
public Map<String, Object> previewImportDetailPricesMany(List<byte[]> bytesList, List<String> names,
|
||||
boolean updateOnly, List<PrcPriceSetDetail> existingDetails, boolean replaceByProductCountry, String countryCode,
|
||||
boolean exclusiveTemplate) throws Exception;
|
||||
|
||||
/**
|
||||
* Sync worker: parse bytes and upsert FIXED detail prices matched by
|
||||
* product + country + zone(if any) + weight band (insert when missing unless updateOnly).
|
||||
|
||||
+11
-9
@@ -2574,7 +2574,7 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
|
||||
Date sheetEffective = parseSheetEffectiveDate(sheet);
|
||||
List<BmsProductCountry> list = new ArrayList<>();
|
||||
int[] countryHeader = findHeaderCell(sheet, "国家");
|
||||
int[] countryHeader = findHeaderCell(sheet, "\u56fd\u5bb6");
|
||||
if (countryHeader == null)
|
||||
{
|
||||
return list;
|
||||
@@ -2582,12 +2582,12 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
int headerRowIdx = countryHeader[0];
|
||||
Row headerRow = sheet.getRow(headerRowIdx);
|
||||
int colCountry = countryHeader[1];
|
||||
int colWeight = findColByHeader(headerRow, "重量", colCountry + 1);
|
||||
int colFreight = findColByHeader(headerRow, "运费", colCountry + 1);
|
||||
int colRegister = findColByHeader(headerRow, "挂号", colCountry + 1);
|
||||
int colSize = findColByHeader(headerRow, "尺寸", colCountry + 1);
|
||||
int colLastMile = findColByHeader(headerRow, "尾程", colCountry + 1);
|
||||
int colLeadTime = findColByHeader(headerRow, "时效", colCountry + 1);
|
||||
int colWeight = findColByHeader(headerRow, "\u91cd\u91cf", colCountry + 1);
|
||||
int colFreight = findColByHeader(headerRow, "\u8fd0\u8d39", colCountry + 1);
|
||||
int colRegister = findColByHeader(headerRow, "\u6302\u53f7", colCountry + 1);
|
||||
int colSize = findColByHeader(headerRow, "\u5c3a\u5bf8", colCountry + 1);
|
||||
int colLastMile = findColByHeader(headerRow, "\u5c3e\u7a0b", colCountry + 1);
|
||||
int colLeadTime = findColByHeader(headerRow, "\u65f6\u6548", colCountry + 1);
|
||||
if (colWeight < 0)
|
||||
{
|
||||
colWeight = colCountry + 1;
|
||||
@@ -2627,7 +2627,8 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
}
|
||||
String countryCell = cellString(row.getCell(colCountry));
|
||||
String weightLabel = cellString(row.getCell(colWeight));
|
||||
if ("国家".equals(countryCell) || weightLabel.contains("重量段"))
|
||||
if ("\u56fd\u5bb6".equals(countryCell)
|
||||
|| (weightLabel != null && weightLabel.contains("\u91cd\u91cf\u6bb5")))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -2847,7 +2848,8 @@ public class BmsProductServiceImpl implements IBmsProductService
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Matcher m = WEIGHT_RANGE_PATTERN.matcher(label.replace(" ", ""));
|
||||
String compact = label.replace(" ", "").replace("\u3000", "");
|
||||
Matcher m = WEIGHT_RANGE_PATTERN.matcher(compact);
|
||||
if (!m.find())
|
||||
{
|
||||
return null;
|
||||
|
||||
+91
-4
@@ -47,6 +47,7 @@ import com.bms.price.mapper.PrcPriceSetVersionMapper;
|
||||
import com.bms.price.mapper.PrcSurchargeMapper;
|
||||
import com.bms.price.mapper.PrcSurchargeRelMapper;
|
||||
import com.bms.price.service.IBmsProductService;
|
||||
import com.bms.price.service.support.ExclusiveHalaraQuoteExcelParser;
|
||||
import com.bms.price.search.IBillSearchStore;
|
||||
import com.bms.price.search.PriceChangeEsLog;
|
||||
import com.bms.price.service.IPrcPriceExcelFileService;
|
||||
@@ -68,6 +69,8 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
private static final String STATUS_REJECT = "R";
|
||||
private static final String STATUS_STOP = "S";
|
||||
private static final String TYPE_FIXED = "FIXED";
|
||||
private static final String CATEGORY_PACKAGE = PrcPriceSet.CATEGORY_PACKAGE;
|
||||
private static final String CATEGORY_EXCLUSIVE = PrcPriceSet.CATEGORY_EXCLUSIVE;
|
||||
private static final String TYPE_DISCOUNT = "DISCOUNT";
|
||||
private static final String VER_DRAFT = "0";
|
||||
private static final String VER_EFFECT = "1";
|
||||
@@ -114,6 +117,9 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
@Autowired
|
||||
private IBmsProductService productService;
|
||||
|
||||
@Autowired
|
||||
private ExclusiveHalaraQuoteExcelParser exclusiveHalaraQuoteExcelParser;
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private PrcPriceSetSaveAsyncRunner saveAsyncRunner;
|
||||
@@ -228,10 +234,11 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
{
|
||||
set.setSetType(TYPE_FIXED);
|
||||
}
|
||||
set.setSetCategory(normalizeSetCategory(set.getSetCategory()));
|
||||
setMapper.insertPrcPriceSet(set);
|
||||
if (StringUtils.isEmpty(set.getPriceSetCode()))
|
||||
{
|
||||
set.setPriceSetCode(String.format("SET%04d", set.getPriceSetId()));
|
||||
set.setPriceSetCode(buildPriceSetCode(set.getSetCategory(), set.getPriceSetId()));
|
||||
setMapper.updatePrcPriceSet(set);
|
||||
}
|
||||
}
|
||||
@@ -240,6 +247,8 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
PrcPriceSet db = requireSet(set.getPriceSetId());
|
||||
assertBasicEditable(db);
|
||||
set.setStatus(db.getStatus());
|
||||
// Category is immutable after create; keep DB value for name uniqueness scope.
|
||||
set.setSetCategory(normalizeSetCategory(db.getSetCategory()));
|
||||
setMapper.updatePrcPriceSet(set);
|
||||
}
|
||||
reportSaveProgress(set, 20, "saving version");
|
||||
@@ -275,6 +284,7 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
throw new ServiceException(MessageUtils.message("price.set.name.empty"));
|
||||
}
|
||||
set.setPriceSetName(set.getPriceSetName().trim());
|
||||
set.setSetCategory(normalizeSetCategory(db.getSetCategory()));
|
||||
if (setMapper.countByName(set) > 0)
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.name.exists"));
|
||||
@@ -641,6 +651,7 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
copy.setPriceSetName(src.getPriceSetName() + "-副本");
|
||||
copy.setPriceSetNote(src.getPriceSetNote());
|
||||
copy.setSetType(src.getSetType());
|
||||
copy.setSetCategory(normalizeSetCategory(src.getSetCategory()));
|
||||
copy.setDefaultDiscount(src.getDefaultDiscount());
|
||||
copy.setDefaultType(src.getDefaultType());
|
||||
copy.setCalculateSign(src.getCalculateSign());
|
||||
@@ -731,8 +742,13 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
{
|
||||
set.setCustomers(db.getCustomers());
|
||||
}
|
||||
if (StringUtils.isEmpty(set.getSetCategory()))
|
||||
{
|
||||
set.setSetCategory(db.getSetCategory());
|
||||
}
|
||||
}
|
||||
}
|
||||
set.setSetCategory(normalizeSetCategory(set.getSetCategory()));
|
||||
|
||||
int nameCount = setMapper.countByName(set);
|
||||
if (StringUtils.isEmpty(set.getPriceSetName()))
|
||||
@@ -1201,9 +1217,18 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
@Override
|
||||
public Map<String, Object> previewImportDetailPrices(byte[] bytes, String filename, boolean updateOnly,
|
||||
List<PrcPriceSetDetail> existingDetails, boolean replaceByProductCountry, String countryCode) throws Exception
|
||||
{
|
||||
return previewImportDetailPrices(bytes, filename, updateOnly, existingDetails, replaceByProductCountry,
|
||||
countryCode, false);
|
||||
}
|
||||
|
||||
public Map<String, Object> previewImportDetailPrices(byte[] bytes, String filename, boolean updateOnly,
|
||||
List<PrcPriceSetDetail> existingDetails, boolean replaceByProductCountry, String countryCode,
|
||||
boolean exclusiveTemplate) throws Exception
|
||||
{
|
||||
boolean replaceScope = replaceByProductCountry || StringUtils.isNotEmpty(countryCode);
|
||||
Map<String, List<BmsProductCountry>> byProduct = parseSetImportExcel(bytes, filename, countryCode);
|
||||
Map<String, List<BmsProductCountry>> byProduct = parseSetImportExcel(bytes, filename, countryCode,
|
||||
exclusiveTemplate);
|
||||
if (byProduct == null || byProduct.isEmpty())
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.import.noPriceRows"));
|
||||
@@ -1391,6 +1416,14 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
public Map<String, Object> previewImportDetailPricesMany(List<byte[]> bytesList, List<String> names,
|
||||
boolean updateOnly, List<PrcPriceSetDetail> existingDetails, boolean replaceByProductCountry, String countryCode)
|
||||
throws Exception
|
||||
{
|
||||
return previewImportDetailPricesMany(bytesList, names, updateOnly, existingDetails, replaceByProductCountry,
|
||||
countryCode, false);
|
||||
}
|
||||
|
||||
public Map<String, Object> previewImportDetailPricesMany(List<byte[]> bytesList, List<String> names,
|
||||
boolean updateOnly, List<PrcPriceSetDetail> existingDetails, boolean replaceByProductCountry, String countryCode,
|
||||
boolean exclusiveTemplate) throws Exception
|
||||
{
|
||||
if (bytesList == null || bytesList.isEmpty())
|
||||
{
|
||||
@@ -1407,7 +1440,7 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
{
|
||||
String filename = names != null && i < names.size() ? names.get(i) : null;
|
||||
last = previewImportDetailPrices(bytesList.get(i), filename, updateOnly, existing, replaceByProductCountry,
|
||||
countryCode);
|
||||
countryCode, exclusiveTemplate);
|
||||
Object details = last == null ? null : last.get("details");
|
||||
if (details instanceof List)
|
||||
{
|
||||
@@ -1429,6 +1462,21 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
private Map<String, List<BmsProductCountry>> parseSetImportExcel(byte[] bytes, String filename, String countryCode)
|
||||
throws Exception
|
||||
{
|
||||
return parseSetImportExcel(bytes, filename, countryCode, false);
|
||||
}
|
||||
|
||||
private Map<String, List<BmsProductCountry>> parseSetImportExcel(byte[] bytes, String filename, String countryCode,
|
||||
boolean exclusiveTemplate) throws Exception
|
||||
{
|
||||
if (exclusiveTemplate)
|
||||
{
|
||||
if (StringUtils.isNotEmpty(countryCode))
|
||||
{
|
||||
throw new ServiceException(
|
||||
"\u4e13\u5c5e\u62a5\u4ef7\u4e0d\u652f\u6301\u5355\u56fd\u5bfc\u5165\uff0c\u8bf7\u4e0a\u4f20\u5b8c\u6574\u5927\u5ba2\u6298\u6263\u62a5\u4ef7\u8868");
|
||||
}
|
||||
return exclusiveHalaraQuoteExcelParser.parse(bytes, filename);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(countryCode))
|
||||
{
|
||||
return productService.parseCountryQuoteExcelByProduct(bytes, filename, countryCode);
|
||||
@@ -1551,7 +1599,9 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
}
|
||||
reportImportProgress(taskId, priceSetId, 20, "parsing excel");
|
||||
boolean replaceScope = replaceByProductCountry || StringUtils.isNotEmpty(countryCode);
|
||||
Map<String, List<BmsProductCountry>> byProduct = parseSetImportExcel(bytes, filename, countryCode);
|
||||
boolean exclusiveTemplate = CATEGORY_EXCLUSIVE.equals(normalizeSetCategory(db.getSetCategory()));
|
||||
Map<String, List<BmsProductCountry>> byProduct = parseSetImportExcel(bytes, filename, countryCode,
|
||||
exclusiveTemplate);
|
||||
if (byProduct == null || byProduct.isEmpty())
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.import.noPriceRows"));
|
||||
@@ -2746,6 +2796,15 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
throw new ServiceException(MessageUtils.message("price.set.discount.range"));
|
||||
}
|
||||
}
|
||||
if (StringUtils.isEmpty(set.getSetCategory()) && set.getPriceSetId() != null)
|
||||
{
|
||||
PrcPriceSet db = setMapper.selectPrcPriceSetHeaderById(set.getPriceSetId());
|
||||
if (db != null)
|
||||
{
|
||||
set.setSetCategory(db.getSetCategory());
|
||||
}
|
||||
}
|
||||
set.setSetCategory(normalizeSetCategory(set.getSetCategory()));
|
||||
if (setMapper.countByName(set) > 0)
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.name.exists"));
|
||||
@@ -2756,6 +2815,34 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
||||
}
|
||||
}
|
||||
|
||||
/** PACKAGE (default) or EXCLUSIVE. */
|
||||
public static String normalizeSetCategory(String setCategory)
|
||||
{
|
||||
if (CATEGORY_EXCLUSIVE.equalsIgnoreCase(StringUtils.trim(setCategory)))
|
||||
{
|
||||
return CATEGORY_EXCLUSIVE;
|
||||
}
|
||||
return CATEGORY_PACKAGE;
|
||||
}
|
||||
|
||||
private static String buildPriceSetCode(String setCategory, Long priceSetId)
|
||||
{
|
||||
String prefix = CATEGORY_EXCLUSIVE.equals(normalizeSetCategory(setCategory)) ? "EXC" : "SET";
|
||||
return String.format("%s%04d", prefix, priceSetId);
|
||||
}
|
||||
|
||||
/** Ensure the package belongs to the expected module category. */
|
||||
public void assertSetCategory(Long priceSetId, String expectedCategory)
|
||||
{
|
||||
PrcPriceSet db = requireSet(priceSetId);
|
||||
String actual = normalizeSetCategory(db.getSetCategory());
|
||||
String expect = normalizeSetCategory(expectedCategory);
|
||||
if (!expect.equals(actual))
|
||||
{
|
||||
throw new ServiceException(MessageUtils.message("price.set.notExists"));
|
||||
}
|
||||
}
|
||||
|
||||
private void validateDetail(PrcPriceSet set, PrcPriceSetDetail detail)
|
||||
{
|
||||
if (StringUtils.isEmpty(detail.getProductCode()))
|
||||
|
||||
+913
@@ -0,0 +1,913 @@
|
||||
package com.bms.price.service.support;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.bms.common.exception.ServiceException;
|
||||
import com.bms.common.utils.StringUtils;
|
||||
import com.bms.price.domain.BmsProduct;
|
||||
import com.bms.price.domain.BmsProductCountry;
|
||||
import com.bms.price.domain.PrcZone;
|
||||
import com.bms.price.mapper.PrcZoneMapper;
|
||||
import com.bms.price.util.ZoneCodeAbbrevs;
|
||||
import com.bms.system.domain.BmsRegion;
|
||||
import com.bms.system.mapper.BmsRegionMapper;
|
||||
|
||||
/**
|
||||
* Exclusive / large-customer (HALARA) quote Excel parser.
|
||||
* Completely separate from ordinary package / product quote Excel parsing.
|
||||
*
|
||||
* Catalog columns: category / country / level / product name / price sheet / product code / feature / lead time.
|
||||
* Price sheets: destination / origin / weight / freight(CNY/KG) / handling(CNY/PCS).
|
||||
*/
|
||||
@Component
|
||||
public class ExclusiveHalaraQuoteExcelParser
|
||||
{
|
||||
private static final String CATALOG_SHEET = "\u4ea7\u54c1\u76ee\u5f55";
|
||||
|
||||
/** Parse 0.01<=W<=0.5 / 0.3<W<=1 */
|
||||
private static final Pattern WEIGHT_W_PATTERN = Pattern.compile(
|
||||
"(\\d+(?:\\.\\d+)?)\\s*[<\u2264]=?\\s*W\\s*[<\u2264]=?\\s*(\\d+(?:\\.\\d+)?)",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
|
||||
/** Parse HALARA bands: 0-0.3kg / 0kg-1kg / 1.01kg-2kg */
|
||||
private static final Pattern WEIGHT_DASH_PATTERN = Pattern.compile(
|
||||
"(?i)(\\d+(?:\\.\\d+)?)\\s*(?:kg)?\\s*[-~\uFF5E\u2014\u2013]\\s*(\\d+(?:\\.\\d+)?)\\s*(?:kg)?");
|
||||
|
||||
@Autowired
|
||||
private BmsRegionMapper regionMapper;
|
||||
|
||||
@Autowired
|
||||
private PrcZoneMapper zoneMapper;
|
||||
|
||||
public Map<String, List<BmsProductCountry>> parse(byte[] bytes, String filename) throws Exception
|
||||
{
|
||||
if (bytes == null || bytes.length == 0)
|
||||
{
|
||||
throw new ServiceException("\u4e13\u5c5e\u62a5\u4ef7\u5bfc\u5165\u6587\u4ef6\u4e3a\u7a7a");
|
||||
}
|
||||
if (filename == null || !(filename.toLowerCase(Locale.ROOT).endsWith(".xlsx")
|
||||
|| filename.toLowerCase(Locale.ROOT).endsWith(".xls")))
|
||||
{
|
||||
throw new ServiceException("\u4e13\u5c5e\u62a5\u4ef7\u4ec5\u652f\u6301 .xls / .xlsx");
|
||||
}
|
||||
try (InputStream is = new ByteArrayInputStream(bytes); Workbook workbook = WorkbookFactory.create(is))
|
||||
{
|
||||
assertHalaraFormat(workbook);
|
||||
Sheet catalog = workbook.getSheet(CATALOG_SHEET);
|
||||
if (catalog == null)
|
||||
{
|
||||
throw new ServiceException("\u4e13\u5c5e\u62a5\u4ef7\u7f3a\u5c11\u300c\u4ea7\u54c1\u76ee\u5f55\u300d");
|
||||
}
|
||||
List<BmsProduct> products = dedupeByCode(parseCatalog(catalog));
|
||||
if (products.isEmpty())
|
||||
{
|
||||
throw new ServiceException("\u4e13\u5c5e\u62a5\u4ef7\u4ea7\u54c1\u76ee\u5f55\u65e0\u6709\u6548\u4ea7\u54c1");
|
||||
}
|
||||
|
||||
Map<String, List<BmsProduct>> ownersBySheet = new LinkedHashMap<String, List<BmsProduct>>();
|
||||
for (BmsProduct product : products)
|
||||
{
|
||||
if (product == null || StringUtils.isEmpty(product.getProductCode()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Sheet productSheet = findSheetForProduct(workbook, product);
|
||||
if (productSheet == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
List<BmsProduct> owners = ownersBySheet.get(productSheet.getSheetName());
|
||||
if (owners == null)
|
||||
{
|
||||
owners = new ArrayList<BmsProduct>();
|
||||
ownersBySheet.put(productSheet.getSheetName(), owners);
|
||||
}
|
||||
owners.add(product);
|
||||
}
|
||||
|
||||
Map<String, BmsRegion> regionByNameCn = loadRegionByNameCn();
|
||||
List<BmsRegion> euRegions = loadEuRegions(regionByNameCn);
|
||||
Map<String, PrcZone> zoneByCountryAndCode = loadZoneByCountryAndCode();
|
||||
Map<String, List<BmsProductCountry>> out = new LinkedHashMap<String, List<BmsProductCountry>>();
|
||||
List<String> dupTips = new ArrayList<String>();
|
||||
|
||||
for (int i = 0; i < workbook.getNumberOfSheets(); i++)
|
||||
{
|
||||
String sheetName = workbook.getSheetName(i);
|
||||
if (shouldSkipSheet(sheetName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Sheet sheet = workbook.getSheetAt(i);
|
||||
if (sheet == null || findHeaderCell(sheet, "\u76ee\u7684\u5730") == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
List<BmsProduct> owners = ownersBySheet.get(sheetName);
|
||||
if (owners == null || owners.isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (BmsProduct owner : owners)
|
||||
{
|
||||
List<BmsProductCountry> rows = parsePriceSheet(sheet, owner, regionByNameCn, euRegions,
|
||||
zoneByCountryAndCode);
|
||||
String tip = dupCountryWeightTip(owner, rows);
|
||||
if (StringUtils.isNotEmpty(tip))
|
||||
{
|
||||
dupTips.add(tip);
|
||||
}
|
||||
if (rows == null || rows.isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String key = owner.getProductCode().trim().toUpperCase(Locale.ROOT);
|
||||
List<BmsProductCountry> existing = out.get(key);
|
||||
if (existing == null)
|
||||
{
|
||||
out.put(key, new ArrayList<BmsProductCountry>(rows));
|
||||
}
|
||||
else
|
||||
{
|
||||
existing.addAll(rows);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!dupTips.isEmpty())
|
||||
{
|
||||
throw new ServiceException("\u4e13\u5c5e\u62a5\u4ef7\u5b58\u5728\u91cd\u590d\u56fd\u5bb6+\u91cd\u91cf\u6bb5\uff1a<br/>" + String.join("<br/>", dupTips));
|
||||
}
|
||||
if (out.isEmpty())
|
||||
{
|
||||
throw new ServiceException("\u4e13\u5c5e\u62a5\u4ef7\u672a\u89e3\u6790\u5230\u6709\u6548\u4ef7\u683c\u884c");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
private void assertHalaraFormat(Workbook workbook)
|
||||
{
|
||||
boolean hasDest = false;
|
||||
for (int i = 0; i < workbook.getNumberOfSheets(); i++)
|
||||
{
|
||||
String sheetName = workbook.getSheetName(i);
|
||||
if (shouldSkipSheet(sheetName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Sheet sheet = workbook.getSheetAt(i);
|
||||
if (sheet != null && findHeaderCell(sheet, "\u76ee\u7684\u5730") != null)
|
||||
{
|
||||
hasDest = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasDest)
|
||||
{
|
||||
throw new ServiceException("\u4e13\u5c5e\u62a5\u4ef7\u4ec5\u652f\u6301\u5927\u5ba2\u6298\u6263\u62a5\u4ef7\u8868\uff08\u542b\u300c\u76ee\u7684\u5730\u300d\u300c\u8fd0\u8d39\u300d\u300c\u64cd\u4f5c\u8d39\u300d\u5217\uff09\uff0c\u8bf7\u52ff\u4f7f\u7528\u666e\u901a\u5957\u9910 Excel");
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean shouldSkipSheet(String name)
|
||||
{
|
||||
if (StringUtils.isEmpty(name))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
String n = name.trim();
|
||||
if (CATALOG_SHEET.equals(n))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if ("Sheet1".equalsIgnoreCase(n) || "Sheet2".equalsIgnoreCase(n))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (n.contains("\u90ae\u7f16") || n.contains("\u8d54\u507f") || n.contains("\u9000\u4ef6")
|
||||
|| n.contains("\u7533\u62a5"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return n.contains("\u7a0e\u7387") || n.toUpperCase(Locale.ROOT).contains("VAT");
|
||||
}
|
||||
|
||||
private List<BmsProduct> parseCatalog(Sheet sheet)
|
||||
{
|
||||
List<BmsProduct> list = new ArrayList<BmsProduct>();
|
||||
int[] header = findHeaderCell(sheet, "\u4ea7\u54c1\u4ee3\u7801");
|
||||
if (header == null)
|
||||
{
|
||||
header = findHeaderCell(sheet, "\u4ea7\u54c1\u540d\u79f0");
|
||||
}
|
||||
if (header == null)
|
||||
{
|
||||
throw new ServiceException("\u4e13\u5c5e\u62a5\u4ef7\u300c\u4ea7\u54c1\u76ee\u5f55\u300d\u672a\u627e\u5230\u8868\u5934\u300c\u4ea7\u54c1\u4ee3\u7801\u300d/\u300c\u4ea7\u54c1\u540d\u79f0\u300d");
|
||||
}
|
||||
int headerRowIdx = header[0];
|
||||
Row head = sheet.getRow(headerRowIdx);
|
||||
int colCode = findColByHeader(head, "\u4ea7\u54c1\u4ee3\u7801", 0);
|
||||
int colName = findColByHeader(head, "\u4ea7\u54c1\u540d\u79f0", 0);
|
||||
int colLevel = findColByHeader(head, "\u7b49\u7ea7", 0);
|
||||
if (colLevel < 0)
|
||||
{
|
||||
colLevel = findColByHeader(head, "\u65f6\u6548", 0);
|
||||
}
|
||||
int colCargo = findColByHeader(head, "\u4ea7\u54c1\u7279\u6027", 0);
|
||||
if (colCargo < 0)
|
||||
{
|
||||
colCargo = findColByHeader(head, "\u8d70\u8d27\u5c5e\u6027", 0);
|
||||
}
|
||||
int colDest = findColByHeader(head, "\u56fd\u5bb6", 0);
|
||||
if (colDest < 0)
|
||||
{
|
||||
colDest = findColByHeader(head, "\u76ee\u7684", 0);
|
||||
}
|
||||
int colLead = findColByHeader(head, "\u53c2\u8003\u65f6\u6548", 0);
|
||||
if (colCode < 0 && colName < 0)
|
||||
{
|
||||
throw new ServiceException("\u4e13\u5c5e\u62a5\u4ef7\u300c\u4ea7\u54c1\u76ee\u5f55\u300d\u7f3a\u5c11\u300c\u4ea7\u54c1\u4ee3\u7801\u300d/\u300c\u4ea7\u54c1\u540d\u79f0\u300d\u5217");
|
||||
}
|
||||
int lastRow = sheet.getLastRowNum();
|
||||
for (int i = headerRowIdx + 1; i <= lastRow; i++)
|
||||
{
|
||||
Row row = sheet.getRow(i);
|
||||
if (row == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String rawCode = colCode >= 0 ? cellString(row.getCell(colCode)) : "";
|
||||
String name = colName >= 0 ? cellString(row.getCell(colName)) : "";
|
||||
if (StringUtils.isEmpty(rawCode) && StringUtils.isEmpty(name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ("\u4ea7\u54c1\u4ee3\u7801".equals(rawCode) || "\u4ea7\u54c1\u540d\u79f0".equals(name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String code = normalizeCode(rawCode);
|
||||
if (StringUtils.isEmpty(code))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
BmsProduct p = new BmsProduct();
|
||||
p.setProductCode(code);
|
||||
p.setProductName(StringUtils.isNotEmpty(name) ? name : code);
|
||||
if (colLevel >= 0)
|
||||
{
|
||||
p.setServiceLevel(cellString(row.getCell(colLevel)));
|
||||
}
|
||||
if (colCargo >= 0)
|
||||
{
|
||||
p.setCargoAttr(cellString(row.getCell(colCargo)));
|
||||
}
|
||||
if (colDest >= 0)
|
||||
{
|
||||
p.setDestRegion(cellString(row.getCell(colDest)));
|
||||
}
|
||||
if (colLead >= 0)
|
||||
{
|
||||
p.setUpdateNote(cellString(row.getCell(colLead)));
|
||||
}
|
||||
list.add(p);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/** Keep dots in codes such as GB.PEXP / DE.PEXP. */
|
||||
private static String normalizeCode(String raw)
|
||||
{
|
||||
if (StringUtils.isEmpty(raw))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String s = raw.trim().replaceAll("[\\(\\uFF08][^\\)\\uFF09]*[\\)\\uFF09]", "").trim();
|
||||
if (StringUtils.isEmpty(s))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Matcher m = Pattern.compile("(?i)^([A-Z0-9._-]+)").matcher(s);
|
||||
if (!m.find())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return m.group(1).toUpperCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
private List<BmsProduct> dedupeByCode(List<BmsProduct> products)
|
||||
{
|
||||
Map<String, BmsProduct> map = new LinkedHashMap<String, BmsProduct>();
|
||||
for (BmsProduct p : products)
|
||||
{
|
||||
if (p == null || StringUtils.isEmpty(p.getProductCode()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String key = p.getProductCode().trim().toUpperCase(Locale.ROOT);
|
||||
if (!map.containsKey(key))
|
||||
{
|
||||
map.put(key, p);
|
||||
}
|
||||
}
|
||||
return new ArrayList<BmsProduct>(map.values());
|
||||
}
|
||||
|
||||
private Sheet findSheetForProduct(Workbook workbook, BmsProduct product)
|
||||
{
|
||||
if (workbook == null || product == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String wantName = product.getProductName();
|
||||
String wantCode = product.getProductCode();
|
||||
if (StringUtils.isNotEmpty(wantName))
|
||||
{
|
||||
Sheet exact = workbook.getSheet(wantName.trim());
|
||||
if (exact != null && !shouldSkipSheet(exact.getSheetName()))
|
||||
{
|
||||
return exact;
|
||||
}
|
||||
}
|
||||
String nameKey = normalizeKey(wantName);
|
||||
String codeKey = normalizeKey(wantCode);
|
||||
String nameBase = sheetNameBase(nameKey);
|
||||
Sheet best = null;
|
||||
int bestScore = 0;
|
||||
for (int i = 0; i < workbook.getNumberOfSheets(); i++)
|
||||
{
|
||||
String sheetName = workbook.getSheetName(i);
|
||||
if (shouldSkipSheet(sheetName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String key = normalizeKey(sheetName);
|
||||
if (StringUtils.isEmpty(key))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int score = 0;
|
||||
if (StringUtils.isNotEmpty(nameKey) && key.equals(nameKey))
|
||||
{
|
||||
return workbook.getSheetAt(i);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(nameKey) && key.contains(nameKey))
|
||||
{
|
||||
score = 100;
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(nameKey) && nameKey.contains(key) && key.length() >= 4)
|
||||
{
|
||||
score = 80;
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(nameBase) && sheetNameBase(key).equals(nameBase)
|
||||
&& nameBase.length() >= 2)
|
||||
{
|
||||
// e.g. catalog "DE express-general" -> sheet "DE express"
|
||||
score = 70;
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(codeKey) && key.contains(codeKey))
|
||||
{
|
||||
score = 60;
|
||||
}
|
||||
if (score > bestScore)
|
||||
{
|
||||
bestScore = score;
|
||||
best = workbook.getSheetAt(i);
|
||||
}
|
||||
}
|
||||
return bestScore >= 60 ? best : null;
|
||||
}
|
||||
|
||||
private static String normalizeKey(String s)
|
||||
{
|
||||
if (s == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
String out = s.trim().toLowerCase(Locale.ROOT);
|
||||
out = out.replace('\u2013', '-').replace('\u2014', '-').replace('\uFF0D', '-');
|
||||
out = out.replace(" ", "").replace("\u3000", "");
|
||||
return out;
|
||||
}
|
||||
|
||||
private static String sheetNameBase(String normalizedKey)
|
||||
{
|
||||
if (StringUtils.isEmpty(normalizedKey))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
int idx = normalizedKey.lastIndexOf('-');
|
||||
if (idx <= 0)
|
||||
{
|
||||
return normalizedKey;
|
||||
}
|
||||
return normalizedKey.substring(0, idx);
|
||||
}
|
||||
|
||||
private List<BmsProductCountry> parsePriceSheet(Sheet sheet, BmsProduct product,
|
||||
Map<String, BmsRegion> regionByNameCn, List<BmsRegion> euRegions,
|
||||
Map<String, PrcZone> zoneByCountryAndCode)
|
||||
{
|
||||
List<BmsProductCountry> list = new ArrayList<BmsProductCountry>();
|
||||
if (sheet == null)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
int[] destHeader = findHeaderCell(sheet, "\u76ee\u7684\u5730");
|
||||
if (destHeader == null)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
int headerRowIdx = destHeader[0];
|
||||
Row headerRow = sheet.getRow(headerRowIdx);
|
||||
int colDest = destHeader[1];
|
||||
int colWeight = findColByHeader(headerRow, "\u91cd\u91cf", colDest + 1);
|
||||
int colFreight = findColByHeader(headerRow, "\u8fd0\u8d39", colDest + 1);
|
||||
int colHandle = findColByHeader(headerRow, "\u64cd\u4f5c\u8d39", colDest + 1);
|
||||
if (colHandle < 0)
|
||||
{
|
||||
colHandle = findColByHeader(headerRow, "\u6302\u53f7", colDest + 1);
|
||||
}
|
||||
int colLead = findColByHeader(headerRow, "\u65f6\u6548", colDest + 1);
|
||||
int colFeature = findColByHeader(headerRow, "\u4ea7\u54c1\u7279\u6027", colDest + 1);
|
||||
int colRemark = findColByHeader(headerRow, "\u5907\u6ce8", colDest + 1);
|
||||
if (colWeight < 0)
|
||||
{
|
||||
colWeight = colDest + 2;
|
||||
}
|
||||
if (colFreight < 0)
|
||||
{
|
||||
colFreight = colDest + 3;
|
||||
}
|
||||
if (colHandle < 0)
|
||||
{
|
||||
colHandle = colDest + 4;
|
||||
}
|
||||
|
||||
String currentDest = null;
|
||||
String currentLead = null;
|
||||
String currentRemark = null;
|
||||
int lastRow = sheet.getLastRowNum();
|
||||
for (int i = headerRowIdx + 1; i <= lastRow; i++)
|
||||
{
|
||||
Row row = sheet.getRow(i);
|
||||
if (row == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String destCell = cellString(row.getCell(colDest));
|
||||
String weightLabel = cellString(row.getCell(colWeight));
|
||||
if ("\u76ee\u7684\u5730".equals(destCell) || (weightLabel != null && weightLabel.contains("\u91cd\u91cf\u6bb5")))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (StringUtils.isNotEmpty(destCell))
|
||||
{
|
||||
currentDest = destCell;
|
||||
currentLead = colLead >= 0 ? emptyToNull(cellString(row.getCell(colLead))) : null;
|
||||
currentRemark = colRemark >= 0 ? emptyToNull(cellString(row.getCell(colRemark))) : null;
|
||||
}
|
||||
if (StringUtils.isEmpty(currentDest))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (currentDest.startsWith("\u4ea7\u54c1\u5b9a\u4e49") || currentDest.startsWith("\u4e00\u3001")
|
||||
|| currentDest.startsWith("\u4e8c\u3001") || currentDest.contains("\u670d\u52a1\u6761\u4ef6"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
BigDecimal[] range = parseWeightRange(weightLabel);
|
||||
if (range == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
BigDecimal freight = cellDecimal(row.getCell(colFreight));
|
||||
BigDecimal handling = cellDecimal(row.getCell(colHandle));
|
||||
ZoneCodeAbbrevs.CountryZoneParts parts = ZoneCodeAbbrevs.splitCountryZone(currentDest);
|
||||
if (parts == null || StringUtils.isEmpty(parts.countryName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String baseCountry = parts.countryName;
|
||||
String zoneLabel = parts.zoneLabel;
|
||||
String feature = colFeature >= 0 ? emptyToNull(cellString(row.getCell(colFeature))) : null;
|
||||
String sizeOrRemark = feature != null ? feature : currentRemark;
|
||||
|
||||
BmsRegion region = resolveRegion(baseCountry, regionByNameCn);
|
||||
if (region != null)
|
||||
{
|
||||
list.add(buildRow(product, region.getCountryNameCn(), region.getCountryCode2(), zoneLabel,
|
||||
zoneByCountryAndCode, range, freight, handling, sizeOrRemark, currentRemark, currentLead));
|
||||
continue;
|
||||
}
|
||||
if (isEuName(baseCountry) && StringUtils.isEmpty(zoneLabel))
|
||||
{
|
||||
if (euRegions == null || euRegions.isEmpty())
|
||||
{
|
||||
throw new ServiceException("\u4e13\u5c5e\u62a5\u4ef7\u89e3\u6790\u5230\u300c\u6b27\u76df\u300d\u4f46\u533a\u57df\u5e93\u65e0\u6b27\u76df\u56fd\u5bb6");
|
||||
}
|
||||
for (BmsRegion eu : euRegions)
|
||||
{
|
||||
list.add(buildRow(product, eu.getCountryNameCn(), eu.getCountryCode2(), null,
|
||||
zoneByCountryAndCode, range, freight, handling, sizeOrRemark, currentRemark, currentLead));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
list.add(buildRow(product, baseCountry, null, zoneLabel, zoneByCountryAndCode, range, freight, handling,
|
||||
sizeOrRemark, currentRemark, currentLead));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private BmsProductCountry buildRow(BmsProduct product, String countryName, String countryCode, String zoneLabel,
|
||||
Map<String, PrcZone> zoneByCountryAndCode, BigDecimal[] range, BigDecimal freight, BigDecimal handling,
|
||||
String sizeLimit, String lastMile, String leadTime)
|
||||
{
|
||||
BmsProductCountry c = new BmsProductCountry();
|
||||
if (product != null)
|
||||
{
|
||||
c.setProductCode(product.getProductCode());
|
||||
c.setProductName(product.getProductName());
|
||||
}
|
||||
c.setCountryName(countryName);
|
||||
c.setCountryCode(countryCode);
|
||||
applyZone(c, countryCode, zoneLabel, zoneByCountryAndCode);
|
||||
c.setWeightMin(range[0]);
|
||||
c.setWeightMax(range[1]);
|
||||
c.setFreightPrice(freight);
|
||||
c.setRegistrationFee(handling);
|
||||
c.setSizeLimit(sizeLimit);
|
||||
c.setLastMile(lastMile);
|
||||
c.setLeadTime(leadTime);
|
||||
return c;
|
||||
}
|
||||
|
||||
private void applyZone(BmsProductCountry c, String countryCode, String zoneLabel,
|
||||
Map<String, PrcZone> zoneByCountryAndCode)
|
||||
{
|
||||
if (StringUtils.isEmpty(zoneLabel))
|
||||
{
|
||||
c.setZoneId(null);
|
||||
c.setZoneCode(null);
|
||||
c.setZoneName(null);
|
||||
return;
|
||||
}
|
||||
String zoneCode = ZoneCodeAbbrevs.toAbbrev(zoneLabel);
|
||||
c.setZoneCode(zoneCode);
|
||||
PrcZone zone = null;
|
||||
if (StringUtils.isNotEmpty(countryCode) && zoneByCountryAndCode != null)
|
||||
{
|
||||
zone = zoneByCountryAndCode.get(countryCode.trim().toUpperCase(Locale.ROOT) + "|"
|
||||
+ zoneCode.trim().toUpperCase(Locale.ROOT));
|
||||
}
|
||||
if (zone != null)
|
||||
{
|
||||
c.setZoneId(zone.getZoneId());
|
||||
c.setZoneCode(zone.getZoneCode());
|
||||
c.setZoneName(zone.getZoneName());
|
||||
}
|
||||
else
|
||||
{
|
||||
c.setZoneId(null);
|
||||
c.setZoneName(StringUtils.isNotEmpty(c.getCountryName())
|
||||
? c.getCountryName() + "(" + zoneCode + ")"
|
||||
: zoneCode);
|
||||
}
|
||||
}
|
||||
|
||||
private BigDecimal[] parseWeightRange(String label)
|
||||
{
|
||||
if (StringUtils.isEmpty(label))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String compact = label.replace(" ", "").replace("\u3000", "");
|
||||
Matcher m = WEIGHT_W_PATTERN.matcher(compact);
|
||||
if (!m.find())
|
||||
{
|
||||
m = WEIGHT_DASH_PATTERN.matcher(compact);
|
||||
if (!m.find())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
BigDecimal min = new BigDecimal(m.group(1));
|
||||
BigDecimal max = new BigDecimal(m.group(2));
|
||||
if (min.compareTo(max) > 0)
|
||||
{
|
||||
BigDecimal tmp = min;
|
||||
min = max;
|
||||
max = tmp;
|
||||
}
|
||||
return new BigDecimal[] { min, max };
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String dupCountryWeightTip(BmsProduct product, List<BmsProductCountry> rows)
|
||||
{
|
||||
if (rows == null || rows.isEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Set<String> seen = new HashSet<String>();
|
||||
for (BmsProductCountry r : rows)
|
||||
{
|
||||
if (r == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String key = String.valueOf(r.getCountryCode()) + "|" + String.valueOf(r.getCountryName())
|
||||
+ "|" + String.valueOf(r.getZoneCode()) + "|"
|
||||
+ (r.getWeightMin() == null ? "" : r.getWeightMin().toPlainString()) + "-"
|
||||
+ (r.getWeightMax() == null ? "" : r.getWeightMax().toPlainString());
|
||||
if (!seen.add(key))
|
||||
{
|
||||
String name = product == null ? "" : product.getProductName();
|
||||
String code = product == null ? "" : product.getProductCode();
|
||||
return (StringUtils.isNotEmpty(name) ? name : code) + " \u91cd\u590d\u56fd\u5bb6+\u91cd\u91cf\u6bb5";
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Map<String, BmsRegion> loadRegionByNameCn()
|
||||
{
|
||||
BmsRegion query = new BmsRegion();
|
||||
query.setStatus("0");
|
||||
List<BmsRegion> regions = regionMapper.selectRegionList(query);
|
||||
Map<String, BmsRegion> map = new HashMap<String, BmsRegion>();
|
||||
if (regions == null)
|
||||
{
|
||||
return map;
|
||||
}
|
||||
for (BmsRegion region : regions)
|
||||
{
|
||||
if (region == null || StringUtils.isEmpty(region.getCountryNameCn()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
map.put(region.getCountryNameCn().trim(), region);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private List<BmsRegion> loadEuRegions(Map<String, BmsRegion> regionByNameCn)
|
||||
{
|
||||
List<BmsRegion> list = new ArrayList<BmsRegion>();
|
||||
if (regionByNameCn == null)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
Set<String> seen = new HashSet<String>();
|
||||
for (BmsRegion region : regionByNameCn.values())
|
||||
{
|
||||
if (region == null || !"1".equals(region.getIsEu()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (StringUtils.isEmpty(region.getCountryCode2()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String code = region.getCountryCode2().toUpperCase(Locale.ROOT);
|
||||
if (seen.add(code))
|
||||
{
|
||||
list.add(region);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private Map<String, PrcZone> loadZoneByCountryAndCode()
|
||||
{
|
||||
Map<String, PrcZone> map = new HashMap<String, PrcZone>();
|
||||
List<PrcZone> list = zoneMapper.selectPrcZoneList(new PrcZone());
|
||||
if (list == null)
|
||||
{
|
||||
return map;
|
||||
}
|
||||
for (PrcZone zone : list)
|
||||
{
|
||||
if (zone == null || StringUtils.isEmpty(zone.getZoneCode()) || StringUtils.isEmpty(zone.getCountryCode()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
map.put(zone.getCountryCode().trim().toUpperCase(Locale.ROOT) + "|"
|
||||
+ zone.getZoneCode().trim().toUpperCase(Locale.ROOT), zone);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private BmsRegion resolveRegion(String excelName, Map<String, BmsRegion> regionByNameCn)
|
||||
{
|
||||
if (StringUtils.isEmpty(excelName) || regionByNameCn == null || regionByNameCn.isEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String name = excelName.trim();
|
||||
BmsRegion exact = regionByNameCn.get(name);
|
||||
if (exact != null)
|
||||
{
|
||||
return exact;
|
||||
}
|
||||
List<BmsRegion> candidates = new ArrayList<BmsRegion>();
|
||||
for (Map.Entry<String, BmsRegion> e : regionByNameCn.entrySet())
|
||||
{
|
||||
String cn = e.getKey();
|
||||
if (cn == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (cn.contains(name) || name.contains(cn))
|
||||
{
|
||||
candidates.add(e.getValue());
|
||||
}
|
||||
}
|
||||
if (candidates.isEmpty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (candidates.size() == 1)
|
||||
{
|
||||
return candidates.get(0);
|
||||
}
|
||||
BmsRegion best = candidates.get(0);
|
||||
for (int i = 1; i < candidates.size(); i++)
|
||||
{
|
||||
String cn = candidates.get(i).getCountryNameCn();
|
||||
if (cn != null && cn.length() > best.getCountryNameCn().length())
|
||||
{
|
||||
best = candidates.get(i);
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
private static boolean isEuName(String name)
|
||||
{
|
||||
if (StringUtils.isEmpty(name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
String n = name.trim();
|
||||
return "\u6b27\u76df".equals(n) || "EU".equalsIgnoreCase(n) || "\u6b27\u6d32\u8054\u76df".equals(n)
|
||||
|| "\u6b27\u76df\u56fd\u5bb6".equals(n) || "\u4e1c\u6b27".equals(n);
|
||||
}
|
||||
|
||||
private static int[] findHeaderCell(Sheet sheet, String headerText)
|
||||
{
|
||||
if (sheet == null || StringUtils.isEmpty(headerText))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int lastRow = Math.min(sheet.getLastRowNum(), 30);
|
||||
int[] containsHit = null;
|
||||
for (int r = 0; r <= lastRow; r++)
|
||||
{
|
||||
Row row = sheet.getRow(r);
|
||||
if (row == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int maxCol = Math.min(Math.max(row.getLastCellNum(), 12), 20);
|
||||
for (int c = 0; c < maxCol; c++)
|
||||
{
|
||||
String v = cellString(row.getCell(c));
|
||||
if (StringUtils.isEmpty(v))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (headerText.equals(v))
|
||||
{
|
||||
return new int[] { r, c };
|
||||
}
|
||||
if (containsHit == null && v.contains(headerText))
|
||||
{
|
||||
containsHit = new int[] { r, c };
|
||||
}
|
||||
}
|
||||
}
|
||||
return containsHit;
|
||||
}
|
||||
|
||||
private static int findColByHeader(Row headerRow, String keyword, int fromCol)
|
||||
{
|
||||
if (headerRow == null || StringUtils.isEmpty(keyword))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
int maxCol = Math.min(Math.max(headerRow.getLastCellNum(), fromCol + 8), 20);
|
||||
for (int c = Math.max(fromCol, 0); c < maxCol; c++)
|
||||
{
|
||||
String v = cellString(headerRow.getCell(c));
|
||||
if (StringUtils.isNotEmpty(v) && v.contains(keyword))
|
||||
{
|
||||
return c;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static String cellString(Cell cell)
|
||||
{
|
||||
if (cell == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
CellType type = cell.getCellType();
|
||||
if (type == CellType.FORMULA)
|
||||
{
|
||||
type = cell.getCachedFormulaResultType();
|
||||
}
|
||||
switch (type)
|
||||
{
|
||||
case STRING:
|
||||
return cell.getStringCellValue() == null ? "" : cell.getStringCellValue().trim();
|
||||
case NUMERIC:
|
||||
if (DateUtil.isCellDateFormatted(cell))
|
||||
{
|
||||
Date d = cell.getDateCellValue();
|
||||
return d == null ? "" : new SimpleDateFormat("yyyy-MM-dd").format(d);
|
||||
}
|
||||
double num = cell.getNumericCellValue();
|
||||
if (Math.floor(num) == num)
|
||||
{
|
||||
return String.valueOf((long) num);
|
||||
}
|
||||
return String.valueOf(num);
|
||||
case BOOLEAN:
|
||||
return String.valueOf(cell.getBooleanCellValue());
|
||||
case BLANK:
|
||||
return "";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private static BigDecimal cellDecimal(Cell cell)
|
||||
{
|
||||
if (cell == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
CellType type = cell.getCellType();
|
||||
if (type == CellType.FORMULA)
|
||||
{
|
||||
type = cell.getCachedFormulaResultType();
|
||||
}
|
||||
try
|
||||
{
|
||||
if (type == CellType.NUMERIC)
|
||||
{
|
||||
return BigDecimal.valueOf(cell.getNumericCellValue());
|
||||
}
|
||||
String s = cellString(cell);
|
||||
if (StringUtils.isEmpty(s))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
s = s.replace(",", "").replace("\uFFE5", "").replace("CNY", "").trim();
|
||||
if (StringUtils.isEmpty(s))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new BigDecimal(s);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String emptyToNull(String s)
|
||||
{
|
||||
return StringUtils.isEmpty(s) ? null : s;
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="priceSetName" column="price_set_name" />
|
||||
<result property="priceSetNote" column="price_set_note" />
|
||||
<result property="setType" column="set_type" />
|
||||
<result property="setCategory" column="set_category" />
|
||||
<result property="defaultDiscount" column="default_discount" />
|
||||
<result property="defaultType" column="default_type" />
|
||||
<result property="calculateSign" column="calculate_sign" />
|
||||
@@ -26,7 +27,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
|
||||
<sql id="selectPrcPriceSetVo">
|
||||
select s.price_set_id, s.price_set_code, s.price_set_name, s.price_set_note,
|
||||
s.set_type, s.default_discount, s.default_type, s.calculate_sign,
|
||||
s.set_type, ifnull(s.set_category, 'PACKAGE') as set_category,
|
||||
s.default_discount, s.default_type, s.calculate_sign,
|
||||
s.status, s.tms_id,
|
||||
s.created_by, s.create_time, s.updated_by, s.update_time,
|
||||
(select count(distinct p.product_code)
|
||||
@@ -52,7 +54,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
|
||||
<select id="selectPrcPriceSetHeaderById" parameterType="Long" resultMap="PrcPriceSetResult">
|
||||
select s.price_set_id, s.price_set_code, s.price_set_name, s.price_set_note,
|
||||
s.set_type, s.default_discount, s.default_type, s.calculate_sign,
|
||||
s.set_type, ifnull(s.set_category, 'PACKAGE') as set_category,
|
||||
s.default_discount, s.default_type, s.calculate_sign,
|
||||
s.status, s.tms_id,
|
||||
s.created_by, s.create_time, s.updated_by, s.update_time,
|
||||
null as product_count, null as customer_count, null as bound_customers
|
||||
@@ -66,6 +69,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="setType != null and setType != ''">
|
||||
AND s.set_type = #{setType}
|
||||
</if>
|
||||
<if test="setCategory != null and setCategory != ''">
|
||||
AND ifnull(s.set_category, 'PACKAGE') = #{setCategory}
|
||||
</if>
|
||||
<if test="status != null and status != ''">
|
||||
AND s.status = #{status}
|
||||
</if>
|
||||
@@ -126,6 +132,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="tmsId != null">
|
||||
AND tms_id = #{tmsId}
|
||||
</if>
|
||||
<if test="setCategory != null and setCategory != ''">
|
||||
AND ifnull(set_category, 'PACKAGE') = #{setCategory}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<insert id="insertPrcPriceSet" parameterType="PrcPriceSet" useGeneratedKeys="true" keyProperty="priceSetId">
|
||||
@@ -134,6 +143,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="priceSetName != null and priceSetName != ''">price_set_name,</if>
|
||||
<if test="priceSetNote != null">price_set_note,</if>
|
||||
<if test="setType != null and setType != ''">set_type,</if>
|
||||
<if test="setCategory != null and setCategory != ''">set_category,</if>
|
||||
<if test="defaultDiscount != null">default_discount,</if>
|
||||
<if test="defaultType != null">default_type,</if>
|
||||
<if test="calculateSign != null">calculate_sign,</if>
|
||||
@@ -146,6 +156,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="priceSetName != null and priceSetName != ''">#{priceSetName},</if>
|
||||
<if test="priceSetNote != null">#{priceSetNote},</if>
|
||||
<if test="setType != null and setType != ''">#{setType},</if>
|
||||
<if test="setCategory != null and setCategory != ''">#{setCategory},</if>
|
||||
<if test="defaultDiscount != null">#{defaultDiscount},</if>
|
||||
<if test="defaultType != null">#{defaultType},</if>
|
||||
<if test="calculateSign != null">#{calculateSign},</if>
|
||||
@@ -163,6 +174,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="priceSetName != null and priceSetName != ''">price_set_name = #{priceSetName},</if>
|
||||
<if test="priceSetNote != null">price_set_note = #{priceSetNote},</if>
|
||||
<if test="setType != null and setType != ''">set_type = #{setType},</if>
|
||||
<if test="setCategory != null and setCategory != ''">set_category = #{setCategory},</if>
|
||||
default_discount = #{defaultDiscount},
|
||||
<if test="defaultType != null">default_type = #{defaultType},</if>
|
||||
<if test="calculateSign != null">calculate_sign = #{calculateSign},</if>
|
||||
|
||||
@@ -1220,6 +1220,7 @@ CREATE TABLE `prc_price_set` (
|
||||
`price_set_name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '报价名称',
|
||||
`price_set_note` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注',
|
||||
`set_type` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'FIXED' COMMENT '计价类型 FIXED=固定价 DISCOUNT=折扣',
|
||||
`set_category` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'PACKAGE' COMMENT '分类 PACKAGE=普通套餐 EXCLUSIVE=专属报价',
|
||||
`default_discount` decimal(5,2) DEFAULT NULL COMMENT '默认折扣百分数 1-99,仅 DISCOUNT',
|
||||
`default_type` char(1) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '默认套餐 Y=默认',
|
||||
`calculate_sign` char(1) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '试算标记 Y=外部试算套餐',
|
||||
@@ -1233,6 +1234,7 @@ CREATE TABLE `prc_price_set` (
|
||||
UNIQUE KEY `uk_price_set_code` (`price_set_code`),
|
||||
KEY `idx_ps_status` (`status`),
|
||||
KEY `idx_ps_type` (`set_type`),
|
||||
KEY `idx_ps_category` (`set_category`),
|
||||
KEY `idx_ps_tms` (`tms_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='价格方案表-报价基本资料';
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
-- Exclusive quote: share prc_price_set via set_category
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
SET @col_exists := (
|
||||
SELECT COUNT(1) FROM information_schema.columns
|
||||
WHERE table_schema = DATABASE()
|
||||
AND table_name = 'prc_price_set'
|
||||
AND column_name = 'set_category'
|
||||
);
|
||||
SET @sql := IF(@col_exists = 0,
|
||||
'ALTER TABLE prc_price_set ADD COLUMN set_category varchar(20) NOT NULL DEFAULT ''PACKAGE'' COMMENT ''分类 PACKAGE=普通套餐 EXCLUSIVE=专属报价'' AFTER set_type',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
UPDATE prc_price_set
|
||||
SET set_category = 'PACKAGE'
|
||||
WHERE set_category IS NULL OR set_category = '';
|
||||
|
||||
SET @idx_exists := (
|
||||
SELECT COUNT(1) FROM information_schema.statistics
|
||||
WHERE table_schema = DATABASE()
|
||||
AND table_name = 'prc_price_set'
|
||||
AND index_name = 'idx_ps_category'
|
||||
);
|
||||
SET @sql := IF(@idx_exists = 0,
|
||||
'ALTER TABLE prc_price_set ADD KEY idx_ps_category (set_category)',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
@@ -0,0 +1,59 @@
|
||||
-- Exclusive quote module menus
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
-- Top-level directory
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||
SELECT 2600, N'专属报价', 0, 55, 'exclusive', NULL, '', '', 1, 0, 'M', '0', '0', '', 'money', 'admin', sysdate(), N'老板客户专属报价'
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2600 OR (path = 'exclusive' AND parent_id = 0 AND menu_type = 'M'));
|
||||
|
||||
SET @exParentId := (SELECT menu_id FROM sys_menu WHERE menu_id = 2600 LIMIT 1);
|
||||
SET @exParentId := IFNULL(@exParentId, (
|
||||
SELECT menu_id FROM sys_menu WHERE path = 'exclusive' AND menu_type = 'M' AND parent_id = 0 ORDER BY menu_id ASC LIMIT 1
|
||||
));
|
||||
|
||||
-- List page
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||
SELECT 2601, N'报价列表', @exParentId, 1, 'quote', 'price/exclusive/exclusiveQuote', '', 'ExclusiveQuote', 1, 0, 'C', '0', '0', 'price:exclusive:list', 'list', 'admin', sysdate(), N'专属报价列表'
|
||||
FROM DUAL WHERE @exParentId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2601 OR perms = 'price:exclusive:list');
|
||||
|
||||
-- Hidden create / detail
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||
SELECT 2609, N'报价新建', @exParentId, 2, 'quoteCreate', 'price/exclusive/create', '', 'ExclusiveQuoteCreate', 1, 0, 'C', '1', '0', 'price:exclusive:add', '#', 'admin', sysdate(), N'专属报价新建/编辑'
|
||||
FROM DUAL WHERE @exParentId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2609 OR path = 'quoteCreate');
|
||||
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||
SELECT 2610, N'报价详情', @exParentId, 3, 'quoteDetail', 'price/exclusive/detail', '', 'ExclusiveQuoteDetail', 1, 0, 'C', '1', '0', 'price:exclusive:query', '#', 'admin', sysdate(), N'专属报价详情'
|
||||
FROM DUAL WHERE @exParentId IS NOT NULL AND NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2610 OR path = 'quoteDetail');
|
||||
|
||||
-- Buttons under list
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||
SELECT 2602, N'查询', 2601, 1, '', NULL, 1, 0, 'F', '0', '0', 'price:exclusive:query', '#', 'admin', sysdate(), N''
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2602 OR (parent_id = 2601 AND perms = 'price:exclusive:query' AND menu_type = 'F'));
|
||||
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||
SELECT 2603, N'新增', 2601, 2, '', NULL, 1, 0, 'F', '0', '0', 'price:exclusive:add', '#', 'admin', sysdate(), N''
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2603 OR (parent_id = 2601 AND perms = 'price:exclusive:add' AND menu_type = 'F'));
|
||||
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||
SELECT 2604, N'修改', 2601, 3, '', NULL, 1, 0, 'F', '0', '0', 'price:exclusive:edit', '#', 'admin', sysdate(), N''
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2604 OR (parent_id = 2601 AND perms = 'price:exclusive:edit' AND menu_type = 'F'));
|
||||
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||
SELECT 2605, N'删除', 2601, 4, '', NULL, 1, 0, 'F', '0', '0', 'price:exclusive:remove', '#', 'admin', sysdate(), N''
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2605 OR (parent_id = 2601 AND perms = 'price:exclusive:remove' AND menu_type = 'F'));
|
||||
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||
SELECT 2606, N'启停/审核', 2601, 5, '', NULL, 1, 0, 'F', '0', '0', 'price:exclusive:audit', '#', 'admin', sysdate(), N''
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2606 OR (parent_id = 2601 AND perms = 'price:exclusive:audit' AND menu_type = 'F'));
|
||||
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||
SELECT 2607, N'强制改价', 2601, 6, '', NULL, 1, 0, 'F', '0', '0', 'price:exclusive:forceEdit', '#', 'admin', sysdate(), N''
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2607 OR (parent_id = 2601 AND perms = 'price:exclusive:forceEdit' AND menu_type = 'F'));
|
||||
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT 1, m.menu_id FROM (
|
||||
SELECT 2600 AS menu_id UNION SELECT 2601 UNION SELECT 2602 UNION SELECT 2603
|
||||
UNION SELECT 2604 UNION SELECT 2605 UNION SELECT 2606 UNION SELECT 2607
|
||||
UNION SELECT 2609 UNION SELECT 2610
|
||||
) m
|
||||
WHERE NOT EXISTS (SELECT 1 FROM sys_role_menu rm WHERE rm.role_id = 1 AND rm.menu_id = m.menu_id);
|
||||
Reference in New Issue
Block a user