+1
-7
@@ -143,13 +143,7 @@ public class SysRoleController extends BaseController
|
||||
{
|
||||
roleService.checkRoleAllowed(role);
|
||||
roleService.checkRoleDataScope(role.getRoleId());
|
||||
int rows = roleService.authDataScope(role);
|
||||
if (rows > 0)
|
||||
{
|
||||
SysRole savedRole = roleService.selectRoleById(role.getRoleId());
|
||||
tokenService.refreshPermissionByRoleId(role.getRoleId(), permissionService, savedRole.getDataScope());
|
||||
}
|
||||
return toAjax(rows);
|
||||
return toAjax(roleService.authDataScope(role));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,378 +0,0 @@
|
||||
package com.bms.ar;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
|
||||
import org.apache.ibatis.session.Configuration;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.function.Executable;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
import org.springframework.aop.aspectj.annotation.AspectJProxyFactory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.bms.ar.domain.ArBill;
|
||||
import com.bms.ar.domain.ArBillExport;
|
||||
import com.bms.ar.domain.ArBillGenerateTask;
|
||||
import com.bms.ar.domain.ArBillLog;
|
||||
import com.bms.ar.domain.vo.ArBillGenerateQuery;
|
||||
import com.bms.ar.domain.vo.ArBillGenerateRequest;
|
||||
import com.bms.ar.domain.vo.ArBillQuery;
|
||||
import com.bms.ar.mapper.ArBillDetailFeeMapper;
|
||||
import com.bms.ar.mapper.ArBillDetailMapper;
|
||||
import com.bms.ar.mapper.ArBillExportMapper;
|
||||
import com.bms.ar.mapper.ArBillGenerateTaskMapper;
|
||||
import com.bms.ar.mapper.ArBillLogMapper;
|
||||
import com.bms.ar.mapper.ArBillMapper;
|
||||
import com.bms.ar.service.ArBillDataScopeService;
|
||||
import com.bms.ar.service.impl.ArBillServiceImpl;
|
||||
import com.bms.common.core.domain.entity.SysRole;
|
||||
import com.bms.common.core.domain.entity.SysUser;
|
||||
import com.bms.common.core.domain.model.LoginUser;
|
||||
import com.bms.common.exception.ServiceException;
|
||||
import com.bms.common.utils.file.OssStorage;
|
||||
import com.bms.framework.aspectj.DataScopeAspect;
|
||||
import com.bms.price.mapper.PrcOrderBillMapper;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/** 不启动应用或连接业务数据库,验证真实切面、Mapper SQL 和业务入口的越权阻断。 */
|
||||
class ArBillDataScopeTest {
|
||||
private ArBillMapper billMapper;
|
||||
private ArBillDetailMapper detailMapper;
|
||||
private ArBillDetailFeeMapper feeMapper;
|
||||
private ArBillExportMapper exportMapper;
|
||||
private ArBillGenerateTaskMapper taskMapper;
|
||||
private ArBillLogMapper logMapper;
|
||||
private PrcOrderBillMapper sourceMapper;
|
||||
private ArBillDataScopeService scopeService;
|
||||
private ArBillServiceImpl service;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(new MockHttpServletRequest()));
|
||||
billMapper = mock(ArBillMapper.class);
|
||||
detailMapper = mock(ArBillDetailMapper.class);
|
||||
feeMapper = mock(ArBillDetailFeeMapper.class);
|
||||
exportMapper = mock(ArBillExportMapper.class);
|
||||
taskMapper = mock(ArBillGenerateTaskMapper.class);
|
||||
logMapper = mock(ArBillLogMapper.class);
|
||||
sourceMapper = mock(PrcOrderBillMapper.class);
|
||||
ArBillDataScopeService scopeTarget = new ArBillDataScopeService();
|
||||
ReflectionTestUtils.setField(scopeTarget, "billMapper", billMapper);
|
||||
ReflectionTestUtils.setField(scopeTarget, "logMapper", logMapper);
|
||||
ReflectionTestUtils.setField(scopeTarget, "generateTaskMapper", taskMapper);
|
||||
scopeService = proxy(scopeTarget);
|
||||
|
||||
ArBillServiceImpl target = new ArBillServiceImpl();
|
||||
ReflectionTestUtils.setField(target, "billMapper", billMapper);
|
||||
ReflectionTestUtils.setField(target, "detailMapper", detailMapper);
|
||||
ReflectionTestUtils.setField(target, "detailFeeMapper", feeMapper);
|
||||
ReflectionTestUtils.setField(target, "exportMapper", exportMapper);
|
||||
ReflectionTestUtils.setField(target, "generateTaskMapper", taskMapper);
|
||||
ReflectionTestUtils.setField(target, "logMapper", logMapper);
|
||||
ReflectionTestUtils.setField(target, "sourceBillMapper", sourceMapper);
|
||||
ReflectionTestUtils.setField(target, "dataScopeService", scopeService);
|
||||
service = proxy(target);
|
||||
login(42L, role(10L, "5", "ar:bill:list"));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void cleanUp() {
|
||||
SecurityContextHolder.clearContext();
|
||||
RequestContextHolder.resetRequestAttributes();
|
||||
PageHelper.clearPage();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource({"1, ALL", "2, role_id = 10", "3, ar_scope_user.dept_id = 200",
|
||||
"4, ancestors", "5, ar_scope_user.user_id = 42"})
|
||||
void appliesAllFiveRoleScopesAndClearsClientSuppliedSql(String scope, String expected) {
|
||||
login(42L, role(10L, scope, "ar:bill:list"));
|
||||
ArBillQuery query = new ArBillQuery();
|
||||
query.getParams().put("dataScope", " OR 1=1 /* client supplied */");
|
||||
service.selectArBillList(query);
|
||||
String sql = scope(query);
|
||||
if ("ALL".equals(expected)) {
|
||||
assertEquals("", sql);
|
||||
} else {
|
||||
assertTrue(sql.contains(expected), sql);
|
||||
}
|
||||
assertFalse(sql.contains("client supplied"));
|
||||
verify(billMapper).selectArBillList(same(query));
|
||||
}
|
||||
|
||||
@Test
|
||||
void mergesOnlyRolesWithBillListPermissionAndIgnoresDisabledRoles() {
|
||||
SysRole disabled = role(13L, "1", "ar:bill:list");
|
||||
disabled.setStatus("1");
|
||||
login(42L, role(10L, "5", "ar:bill:list"), role(11L, "3", "ar:bill:list"),
|
||||
role(12L, "1", "other:list"), disabled);
|
||||
ArBillQuery query = new ArBillQuery();
|
||||
service.selectArBillList(query);
|
||||
assertTrue(scope(query).contains("ar_scope_user.user_id = 42"));
|
||||
assertTrue(scope(query).contains("ar_scope_user.dept_id = 200"));
|
||||
assertTrue(scope(query).contains(" OR "));
|
||||
|
||||
login(42L, role(10L, "5", "ar:bill:list"), role(11L, "1", "ar:bill:list"));
|
||||
service.selectArBillList(query);
|
||||
assertEquals("", scope(query));
|
||||
}
|
||||
|
||||
@Test
|
||||
void superAdminIsUnrestrictedButNoMatchingRoleGetsNoRows() {
|
||||
ArBillQuery query = new ArBillQuery();
|
||||
login(1L);
|
||||
service.selectArBillList(query);
|
||||
assertEquals("", scope(query));
|
||||
login(42L, role(10L, "1", "other:list"));
|
||||
service.selectArBillList(query);
|
||||
assertTrue(scope(query).contains("ar_scope_user.dept_id = 0"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void combinesCustomDepartmentRoles() {
|
||||
login(42L, role(10L, "2", "ar:bill:list"), role(11L, "2", "ar:bill:list"));
|
||||
ArBillQuery query = new ArBillQuery();
|
||||
service.selectArBillList(query);
|
||||
assertTrue(scope(query).contains("role_id in (10,11)"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsBillIdsBeforeReadingDetailsOrRunningActions() {
|
||||
forbidden(() -> service.selectArBillById(80L));
|
||||
forbidden(() -> service.selectArBillDetails(80L));
|
||||
forbidden(() -> service.selectArBillDetailFees(80L, 1L));
|
||||
forbidden(() -> service.selectExports(80L));
|
||||
forbidden(() -> service.confirmBill(80L, null, "tester", "confirm"));
|
||||
forbidden(() -> service.voidBill(80L, null, "tester", "void"));
|
||||
forbidden(() -> service.exportBill(80L, "tester", "export"));
|
||||
verifyNoInteractions(detailMapper, feeMapper, exportMapper, logMapper);
|
||||
verify(billMapper, never()).selectArBillByIdForUpdate(anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
void checksExportAndGenerateTaskOwnershipThroughTheirBill() throws Exception {
|
||||
ArBillExport export = new ArBillExport();
|
||||
export.setArBillId(80L);
|
||||
export.setExportStatus("SUCCESS");
|
||||
export.setStorageKey("oss://test/bill.xlsx");
|
||||
when(exportMapper.selectById(9L)).thenReturn(export);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
forbidden(() -> service.selectExport(9L));
|
||||
forbidden(() -> service.downloadExport(9L, response));
|
||||
assertEquals(0, response.getContentAsByteArray().length);
|
||||
assertNull(response.getHeader("Content-Disposition"));
|
||||
|
||||
ArBillGenerateTask task = new ArBillGenerateTask();
|
||||
task.setArBillId(80L);
|
||||
when(taskMapper.selectById(3L)).thenReturn(task);
|
||||
forbidden(() -> service.selectGenerateTask(3L));
|
||||
forbidden(() -> service.cancelGenerateTask(3L, "tester", "cancel"));
|
||||
forbidden(() -> service.retryGenerateTask(3L, "tester", "retry"));
|
||||
verify(taskMapper, never()).markCancelRequested(anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
void authorizedBillStillReturnsMaskedAccountAndDownloadsItsExport() throws Exception {
|
||||
ArBill bill = new ArBill();
|
||||
bill.setArBillId(80L);
|
||||
bill.setBankAccountNo("123456780504");
|
||||
when(billMapper.selectArBillByDataScope(any())).thenReturn(bill);
|
||||
assertEquals("****0504", service.selectArBillById(80L).getBankAccountNo());
|
||||
ArBillExport export = new ArBillExport();
|
||||
export.setArBillId(80L);
|
||||
export.setExportStatus("SUCCESS");
|
||||
export.setStorageKey("oss://test/bill.xlsx");
|
||||
export.setFileName("bill.xlsx");
|
||||
when(exportMapper.selectById(9L)).thenReturn(export);
|
||||
OssStorage storage = mock(OssStorage.class);
|
||||
ReflectionTestUtils.setField(service, "ossStorage", storage);
|
||||
doAnswer(invocation -> {
|
||||
((OutputStream) invocation.getArgument(1)).write(new byte[] {1, 2, 3});
|
||||
return null;
|
||||
}).when(storage).download(eq("oss://test/bill.xlsx"), any(OutputStream.class));
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
service.downloadExport(9L, response);
|
||||
assertArrayEquals(new byte[] {1, 2, 3}, response.getContentAsByteArray());
|
||||
assertTrue(response.getHeader("Content-Disposition").contains("bill.xlsx"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void permissionLookupPreservesDetailPaginationAndClearsItOnDenial() {
|
||||
Page<Object> page = PageHelper.startPage(3, 20);
|
||||
page.setOrderBy("detail_no desc");
|
||||
when(billMapper.selectArBillByDataScope(any())).thenAnswer(invocation -> {
|
||||
assertNull(PageHelper.getLocalPage(), "权限校验不能消耗明细分页");
|
||||
assertTrue(scope(invocation.getArgument(0)).contains("ar_scope_user.user_id = 42"));
|
||||
return new ArBill();
|
||||
});
|
||||
when(detailMapper.selectByBillId(80L)).thenAnswer(invocation -> {
|
||||
assertSame(page, PageHelper.getLocalPage());
|
||||
assertEquals("detail_no desc", page.getOrderBy());
|
||||
PageHelper.clearPage();
|
||||
return Collections.emptyList();
|
||||
});
|
||||
service.selectArBillDetails(80L);
|
||||
assertNull(PageHelper.getLocalPage());
|
||||
|
||||
doReturn(null).when(billMapper).selectArBillByDataScope(any());
|
||||
PageHelper.startPage(3, 20);
|
||||
forbidden(() -> service.selectArBillDetails(81L));
|
||||
assertNull(PageHelper.getLocalPage(), "拒绝请求后不能向下一请求遗留分页");
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsCustomerPreviewAndGenerationBeforeReadingSourceOrders() {
|
||||
ArBillGenerateQuery preview = new ArBillGenerateQuery();
|
||||
preview.setCustomerId(100L);
|
||||
preview.setBillPeriodEnd(new Date());
|
||||
forbidden(() -> service.previewBill(preview));
|
||||
forbidden(() -> service.sumPreviewBill(preview));
|
||||
ArBillGenerateRequest request = new ArBillGenerateRequest();
|
||||
request.setCustomerId(100L);
|
||||
request.setBillName("test");
|
||||
request.setBillPeriodEnd(new Date());
|
||||
forbidden(() -> service.generateBill(request, "tester", "generate"));
|
||||
verifyNoInteractions(sourceMapper, taskMapper);
|
||||
}
|
||||
|
||||
@Test
|
||||
void authorizedCustomerPreviewRetainsItsOriginalPagination() {
|
||||
Page<Object> page = PageHelper.startPage(2, 10);
|
||||
when(billMapper.selectCustomerIdByDataScope(any())).thenAnswer(invocation -> {
|
||||
assertNull(PageHelper.getLocalPage());
|
||||
return 100L;
|
||||
});
|
||||
doAnswer(invocation -> {
|
||||
assertSame(page, PageHelper.getLocalPage());
|
||||
PageHelper.clearPage();
|
||||
return Collections.emptyList();
|
||||
}).when(sourceMapper).selectPrcOrderBillByCustomerPeriod(eq(100L), any(), anyList(), anyList(),
|
||||
any(), any(), anyList(), any(), any());
|
||||
ArBillGenerateQuery preview = new ArBillGenerateQuery();
|
||||
preview.setCustomerId(100L);
|
||||
preview.setBillPeriodEnd(new Date());
|
||||
service.previewBill(preview);
|
||||
assertNull(PageHelper.getLocalPage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void exportIdempotencyCannotReturnAnExportFromAnotherBill() {
|
||||
when(billMapper.selectArBillByDataScope(any())).thenReturn(new ArBill());
|
||||
ArBillLog previous = new ArBillLog();
|
||||
previous.setObjectId("9");
|
||||
when(logMapper.selectSuccessByRequestId(anyString(), anyString(), anyString())).thenReturn(previous);
|
||||
ArBillExport export = new ArBillExport();
|
||||
export.setArBillId(81L);
|
||||
when(exportMapper.selectById(9L)).thenReturn(export);
|
||||
ServiceException denied = assertThrows(ServiceException.class,
|
||||
() -> service.exportBill(80L, "tester", "reused"));
|
||||
assertTrue(denied.getMessage().contains("其他账单"));
|
||||
verify(exportMapper, never()).insert(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void logAndActiveTaskQueriesUseTheSameRoleScope() {
|
||||
scopeService.selectLogs(new ArBillQuery(), new ArBillLog());
|
||||
scopeService.selectActiveGenerateTasks(new ArBillQuery(), "tester");
|
||||
verify(logMapper).selectList(any(), argThat(params ->
|
||||
params.get("dataScope").toString().contains("ar_scope_user.user_id = 42")));
|
||||
verify(taskMapper).selectActiveByCreateBy(eq("tester"), argThat(params ->
|
||||
params.get("dataScope").toString().contains("ar_scope_user.user_id = 42")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void allReadMappersRenderScopedSqlAndKeepNormalFilters() throws Exception {
|
||||
Configuration configuration = new Configuration();
|
||||
configuration.getTypeAliasRegistry().registerAlias("ArBill", ArBill.class);
|
||||
configuration.getTypeAliasRegistry().registerAlias("ArBillLog", ArBillLog.class);
|
||||
configuration.getTypeAliasRegistry().registerAlias("ArBillGenerateTask", ArBillGenerateTask.class);
|
||||
for (String name : List.of("ArBillMapper", "ArBillLogMapper", "ArBillGenerateTaskMapper")) {
|
||||
String resource = "mapper/ar/" + name + ".xml";
|
||||
try (InputStream input = new ClassPathResource(resource).getInputStream()) {
|
||||
new XMLMapperBuilder(input, configuration, resource, configuration.getSqlFragments()).parse();
|
||||
}
|
||||
}
|
||||
ArBillQuery query = new ArBillQuery();
|
||||
query.setArBillId(80L);
|
||||
query.setCustomerId(100L);
|
||||
query.setStatus("CONFIRMED");
|
||||
service.selectArBillList(query);
|
||||
String listSql = sql(configuration, "ArBillMapper.selectArBillList", query);
|
||||
assertTrue(listSql.contains("status = ?"));
|
||||
assertTrue(listSql.contains("customer_id = ?"));
|
||||
assertTrue(listSql.contains("ar_scope_customer.customer_id = ar_bill.customer_id"));
|
||||
assertTrue(listSql.contains("ar_scope_id_user.user_id is null"), "历史工号仅在ID不存在时兜底");
|
||||
assertTrue(listSql.contains("exists ("), "EXISTS 避免业务员关联放大列表和分页总数");
|
||||
assertFalse(listSql.contains("${"));
|
||||
for (String statement : List.of("ArBillMapper.selectArBillByDataScope", "ArBillMapper.selectCustomerIdByDataScope")) {
|
||||
assertTrue(sql(configuration, statement, query).contains("ar_scope_user.user_id = 42"));
|
||||
}
|
||||
Map<String, Object> logs = Map.of("query", new ArBillLog(), "params", query.getParams());
|
||||
assertTrue(sql(configuration, "ArBillLogMapper.selectList", logs).contains("ar_scope_customer.customer_id = b.customer_id"));
|
||||
Map<String, Object> tasks = Map.of("createBy", "tester", "params", query.getParams());
|
||||
assertTrue(sql(configuration, "ArBillGenerateTaskMapper.selectActiveByCreateBy", tasks)
|
||||
.contains("b.ar_bill_id = ar_bill_generate_task.ar_bill_id"));
|
||||
login(42L, role(10L, "1", "ar:bill:list"));
|
||||
service.selectArBillList(query);
|
||||
assertFalse(sql(configuration, "ArBillMapper.selectArBillList", query).contains("ar_scope_customer"));
|
||||
}
|
||||
|
||||
private String sql(Configuration configuration, String statement, Object parameters) {
|
||||
return configuration.getMappedStatement("com.bms.ar.mapper." + statement).getBoundSql(parameters)
|
||||
.getSql().replaceAll("\\s+", " ");
|
||||
}
|
||||
|
||||
private String scope(ArBillQuery query) {
|
||||
return String.valueOf(query.getParams().get("dataScope"));
|
||||
}
|
||||
|
||||
private void forbidden(Executable action) {
|
||||
assertEquals(403, assertThrows(ServiceException.class, action).getCode());
|
||||
}
|
||||
|
||||
private SysRole role(Long id, String scope, String permission) {
|
||||
SysRole role = new SysRole(id);
|
||||
role.setDataScope(scope);
|
||||
role.setStatus("0");
|
||||
role.setPermissions(Set.of(permission));
|
||||
return role;
|
||||
}
|
||||
|
||||
private void login(Long userId, SysRole... roles) {
|
||||
SysUser user = new SysUser(userId);
|
||||
user.setDeptId(200L);
|
||||
user.setUserName("tester");
|
||||
user.setRoles(List.of(roles));
|
||||
LoginUser login = new LoginUser(userId, 200L, user, Set.of("ar:bill:list"));
|
||||
SecurityContextHolder.getContext().setAuthentication(
|
||||
new UsernamePasswordAuthenticationToken(login, null, Collections.emptyList()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T proxy(T target) {
|
||||
AspectJProxyFactory factory = new AspectJProxyFactory(target);
|
||||
factory.setProxyTargetClass(true);
|
||||
factory.addAspect(new DataScopeAspect());
|
||||
return (T) factory.getProxy();
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package com.bms.system;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import com.bms.common.constant.CacheConstants;
|
||||
import com.bms.common.core.domain.entity.SysRole;
|
||||
import com.bms.common.core.domain.entity.SysUser;
|
||||
import com.bms.common.core.domain.model.LoginUser;
|
||||
import com.bms.common.core.redis.RedisCache;
|
||||
import com.bms.framework.web.service.SysPermissionService;
|
||||
import com.bms.framework.web.service.TokenService;
|
||||
import com.bms.system.service.ISysRoleService;
|
||||
import com.bms.web.controller.system.SysRoleController;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
class SysRoleDataScopeRefreshTest {
|
||||
@Test
|
||||
void savingDataScopeRefreshesOnlineUsersWithPersistedScope() {
|
||||
ISysRoleService roles = mock(ISysRoleService.class);
|
||||
TokenService tokens = mock(TokenService.class);
|
||||
SysPermissionService permissions = mock(SysPermissionService.class);
|
||||
SysRoleController controller = new SysRoleController();
|
||||
ReflectionTestUtils.setField(controller, "roleService", roles);
|
||||
ReflectionTestUtils.setField(controller, "tokenService", tokens);
|
||||
ReflectionTestUtils.setField(controller, "permissionService", permissions);
|
||||
SysRole submitted = new SysRole(10L);
|
||||
submitted.setDataScope("5");
|
||||
SysRole persisted = new SysRole(10L);
|
||||
persisted.setDataScope("5");
|
||||
when(roles.authDataScope(submitted)).thenReturn(1);
|
||||
when(roles.selectRoleById(10L)).thenReturn(persisted);
|
||||
controller.dataScope(submitted);
|
||||
verify(tokens).refreshPermissionByRoleId(10L, permissions, "5");
|
||||
}
|
||||
|
||||
@Test
|
||||
void replacesCachedDataScopeBeforeSavingSessionAndPreservesOtherRoles() {
|
||||
RedisCache redis = mock(RedisCache.class);
|
||||
SysPermissionService permissions = mock(SysPermissionService.class);
|
||||
TokenService tokens = spy(new TokenService());
|
||||
ReflectionTestUtils.setField(tokens, "redisCache", redis);
|
||||
doNothing().when(tokens).refreshToken(any());
|
||||
SysRole target = new SysRole(10L);
|
||||
target.setDataScope("1");
|
||||
SysRole other = new SysRole(11L);
|
||||
other.setDataScope("3");
|
||||
SysUser user = new SysUser(42L);
|
||||
user.setRoles(List.of(target, other));
|
||||
LoginUser login = new LoginUser(42L, 200L, user, Set.of("ar:bill:list"));
|
||||
String key = CacheConstants.LOGIN_TOKEN_KEY + "test";
|
||||
when(redis.keys(CacheConstants.LOGIN_TOKEN_KEY + "*")).thenReturn(List.of(key));
|
||||
when(redis.getCacheObject(key)).thenReturn(login);
|
||||
when(permissions.getMenuPermission(user)).thenAnswer(invocation -> {
|
||||
assertEquals("5", target.getDataScope());
|
||||
return Set.of("ar:bill:list");
|
||||
});
|
||||
tokens.refreshPermissionByRoleId(10L, permissions, "5");
|
||||
assertEquals("5", login.getUser().getRoles().get(0).getDataScope());
|
||||
assertEquals("3", other.getDataScope());
|
||||
verify(tokens).refreshToken(login);
|
||||
}
|
||||
}
|
||||
@@ -238,12 +238,6 @@ public class TokenService
|
||||
* @param permissionService 权限服务
|
||||
*/
|
||||
public void refreshPermissionByRoleId(Long roleId, SysPermissionService permissionService)
|
||||
{
|
||||
refreshPermissionByRoleId(roleId, permissionService, null);
|
||||
}
|
||||
|
||||
/** 数据范围变更时同步更新在线登录信息中的角色快照。 */
|
||||
public void refreshPermissionByRoleId(Long roleId, SysPermissionService permissionService, String dataScope)
|
||||
{
|
||||
// 扫描所有在线 token
|
||||
String pattern = CacheConstants.LOGIN_TOKEN_KEY + "*";
|
||||
@@ -267,12 +261,6 @@ public class TokenService
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (dataScope != null)
|
||||
{
|
||||
loginUser.getUser().getRoles().stream()
|
||||
.filter(r -> roleId.equals(r.getRoleId()))
|
||||
.forEach(r -> r.setDataScope(dataScope));
|
||||
}
|
||||
// 刷新权限缓存
|
||||
loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
|
||||
refreshToken(loginUser);
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.bms.ar.mapper;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import com.bms.ar.domain.ArBillGenerateTask;
|
||||
@@ -15,8 +14,7 @@ public interface ArBillGenerateTaskMapper {
|
||||
|
||||
ArBillGenerateTask selectByRequestToken(String requestToken);
|
||||
|
||||
List<ArBillGenerateTask> selectActiveByCreateBy(@Param("createBy") String createBy,
|
||||
@Param("params") Map<String, Object> params);
|
||||
List<ArBillGenerateTask> selectActiveByCreateBy(@Param("createBy") String createBy);
|
||||
|
||||
List<ArBillGenerateTask> selectWaiting(@Param("limit") int limit);
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package com.bms.ar.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import com.bms.ar.domain.ArBillLog;
|
||||
|
||||
public interface ArBillLogMapper
|
||||
{
|
||||
List<ArBillLog> selectList(@Param("query") ArBillLog query, @Param("params") Map<String, Object> params);
|
||||
List<ArBillLog> selectList(ArBillLog query);
|
||||
|
||||
ArBillLog selectSuccessByRequestId(@Param("requestId") String requestId,
|
||||
@Param("objectType") String objectType,
|
||||
|
||||
@@ -11,10 +11,6 @@ import com.bms.ar.domain.vo.ArBillQuery;
|
||||
public interface ArBillMapper {
|
||||
List<ArBill> selectArBillList(ArBillQuery query);
|
||||
|
||||
ArBill selectArBillByDataScope(ArBillQuery query);
|
||||
|
||||
Long selectCustomerIdByDataScope(ArBillQuery query);
|
||||
|
||||
ArBill selectArBillById(Long arBillId);
|
||||
|
||||
ArBill selectArBillByBillNo(String billNo);
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
package com.bms.ar.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.bms.ar.domain.ArBill;
|
||||
import com.bms.ar.domain.ArBillGenerateTask;
|
||||
import com.bms.ar.domain.ArBillLog;
|
||||
import com.bms.ar.domain.vo.ArBillQuery;
|
||||
import com.bms.ar.mapper.ArBillGenerateTaskMapper;
|
||||
import com.bms.ar.mapper.ArBillLogMapper;
|
||||
import com.bms.ar.mapper.ArBillMapper;
|
||||
import com.bms.common.annotation.DataScope;
|
||||
import com.bms.common.constant.HttpStatus;
|
||||
import com.bms.common.exception.ServiceException;
|
||||
|
||||
/**
|
||||
* 按客户归属业务员和其部门校验账单可见范围。
|
||||
* 独立 Bean 保证内部业务调用也经过 DataScope 切面;范围始终取具有账单列表权限的角色。
|
||||
*/
|
||||
@Service
|
||||
public class ArBillDataScopeService {
|
||||
@Autowired
|
||||
private ArBillMapper billMapper;
|
||||
@Autowired
|
||||
private ArBillLogMapper logMapper;
|
||||
@Autowired
|
||||
private ArBillGenerateTaskMapper generateTaskMapper;
|
||||
|
||||
@DataScope(deptAlias = "ar_scope_user", userAlias = "ar_scope_user", permission = "ar:bill:list")
|
||||
public ArBill requireBill(ArBillQuery query) {
|
||||
return withoutPagination(() -> {
|
||||
ArBill bill = query.getArBillId() == null ? null : billMapper.selectArBillByDataScope(query);
|
||||
if (bill == null) {
|
||||
throw new ServiceException("应收账单不存在或无权访问", HttpStatus.FORBIDDEN);
|
||||
}
|
||||
return bill;
|
||||
});
|
||||
}
|
||||
|
||||
@DataScope(deptAlias = "ar_scope_user", userAlias = "ar_scope_user", permission = "ar:bill:list")
|
||||
public void requireCustomer(ArBillQuery query) {
|
||||
withoutPagination(() -> {
|
||||
Long customerId = query.getCustomerId() == null || query.getCustomerId() <= 0
|
||||
? null : billMapper.selectCustomerIdByDataScope(query);
|
||||
if (customerId == null || customerId <= 0) {
|
||||
throw new ServiceException("客户不存在或无权访问该客户的应收账单", HttpStatus.FORBIDDEN);
|
||||
}
|
||||
return customerId;
|
||||
});
|
||||
}
|
||||
|
||||
@DataScope(deptAlias = "ar_scope_user", userAlias = "ar_scope_user", permission = "ar:bill:list")
|
||||
public List<ArBillLog> selectLogs(ArBillQuery scope, ArBillLog query) {
|
||||
return logMapper.selectList(query, scope.getParams());
|
||||
}
|
||||
|
||||
@DataScope(deptAlias = "ar_scope_user", userAlias = "ar_scope_user", permission = "ar:bill:list")
|
||||
public List<ArBillGenerateTask> selectActiveGenerateTasks(ArBillQuery scope, String operator) {
|
||||
return generateTaskMapper.selectActiveByCreateBy(operator, scope.getParams());
|
||||
}
|
||||
|
||||
/** 权限校验 SQL 不消耗调用方为明细/订单预览设置的分页,拒绝访问时清理分页。 */
|
||||
private <T> T withoutPagination(Supplier<T> lookup) {
|
||||
Page<?> pendingPage = PageHelper.getLocalPage();
|
||||
PageHelper.clearPage();
|
||||
try {
|
||||
T result = lookup.get();
|
||||
if (pendingPage != null) {
|
||||
PageHelper.setLocalPage(pendingPage);
|
||||
}
|
||||
return result;
|
||||
} catch (RuntimeException | Error e) {
|
||||
PageHelper.clearPage();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,20 +13,16 @@ import com.bms.ar.enums.ArLogOperationType;
|
||||
import com.bms.ar.enums.ArLogResult;
|
||||
import com.bms.ar.mapper.ArBillLogMapper;
|
||||
import com.bms.ar.service.IArBillLogService;
|
||||
import com.bms.ar.service.ArBillDataScopeService;
|
||||
import com.bms.ar.domain.vo.ArBillQuery;
|
||||
import com.bms.common.utils.uuid.IdUtils;
|
||||
|
||||
@Service
|
||||
public class ArBillLogServiceImpl implements IArBillLogService {
|
||||
@Autowired
|
||||
private ArBillLogMapper logMapper;
|
||||
@Autowired
|
||||
private ArBillDataScopeService dataScopeService;
|
||||
|
||||
@Override
|
||||
public List<ArBillLog> selectLogList(ArBillLog query) {
|
||||
return dataScopeService.selectLogs(new ArBillQuery(), query);
|
||||
return logMapper.selectList(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -75,13 +75,11 @@ import com.bms.ar.mapper.ArBankAccountMapper;
|
||||
import com.bms.ar.mapper.ArExportTemplateMapper;
|
||||
import com.bms.ar.service.IArBillLogService;
|
||||
import com.bms.ar.service.IArBillService;
|
||||
import com.bms.ar.service.ArBillDataScopeService;
|
||||
import com.bms.ar.domain.vo.ArBillActionRequest;
|
||||
import com.bms.ar.domain.vo.ArBillGenerateQuery;
|
||||
import com.bms.ar.domain.vo.ArBillGenerateRequest;
|
||||
import com.bms.ar.domain.vo.ArBillQuery;
|
||||
import com.bms.common.config.BmsConfig;
|
||||
import com.bms.common.annotation.DataScope;
|
||||
import com.bms.common.exception.ServiceException;
|
||||
import com.bms.common.utils.DateUtils;
|
||||
import com.bms.common.utils.SecurityUtils;
|
||||
@@ -199,8 +197,6 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
@Autowired
|
||||
private IArBillLogService logService;
|
||||
@Autowired
|
||||
private ArBillDataScopeService dataScopeService;
|
||||
@Autowired
|
||||
private ApplicationEventPublisher eventPublisher;
|
||||
@Autowired
|
||||
private PrcOrderBillMapper sourceBillMapper;
|
||||
@@ -215,7 +211,6 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
* 查询账单列表,并对返回给前端的收款账号做脱敏。
|
||||
*/
|
||||
@Override
|
||||
@DataScope(deptAlias = "ar_scope_user", userAlias = "ar_scope_user", permission = "ar:bill:list")
|
||||
public List<ArBill> selectArBillList(ArBillQuery query) {
|
||||
long startedAt = System.nanoTime();
|
||||
List<ArBill> bills = billMapper.selectArBillList(query);
|
||||
@@ -234,7 +229,10 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
@Override
|
||||
public ArBill selectArBillById(Long arBillId) {
|
||||
long startedAt = System.nanoTime();
|
||||
ArBill bill = requireBillDataScope(arBillId);
|
||||
ArBill bill = billMapper.selectArBillById(arBillId);
|
||||
if (bill == null) {
|
||||
throw new ServiceException("应收账单不存在");
|
||||
}
|
||||
bill.setBankAccountNo(maskAccount(bill.getBankAccountNo()));
|
||||
bill.setExports(exportMapper.selectByBillId(arBillId));
|
||||
log.debug("应收账单详情查询完成,arBillId={}, status={}, exportCount={}, costMs={}",
|
||||
@@ -249,7 +247,6 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
@Override
|
||||
public List<ArBillDetail> selectArBillDetails(Long arBillId) {
|
||||
long startedAt = System.nanoTime();
|
||||
requireBillDataScope(arBillId);
|
||||
List<ArBillDetail> details = detailMapper.selectByBillId(arBillId);
|
||||
log.debug("应收账单明细查询完成,arBillId={}, resultCount={}, costMs={}",
|
||||
arBillId, details.size(), elapsedMillis(startedAt));
|
||||
@@ -262,7 +259,6 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
@Override
|
||||
public List<ArBillDetailFee> selectArBillDetailFees(Long arBillId, Long detailId) {
|
||||
long startedAt = System.nanoTime();
|
||||
requireBillDataScope(arBillId);
|
||||
List<ArBillDetailFee> fees = detailFeeMapper.selectByBillIdAndDetailId(arBillId, detailId);
|
||||
log.debug("应收账单费用明细查询完成,arBillId={}, detailId={}, resultCount={}, costMs={}",
|
||||
arBillId, detailId, fees.size(), elapsedMillis(startedAt));
|
||||
@@ -303,7 +299,6 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
public List<PrcOrderBill> previewBill(ArBillGenerateQuery query) {
|
||||
long startedAt = System.nanoTime();
|
||||
validatePreviewQuery(query);
|
||||
requireCustomerDataScope(query.getCustomerId());
|
||||
List<String> orderIdentifiers = normalizeOrderIdentifiers(query.getOrderOrTrackingNo());
|
||||
List<String> excludeOrderIdentifiers = normalizeOrderIdentifiers(query.getExcludeOrderOrTrackingNo());
|
||||
List<PrcOrderBill> result = sourceBillMapper.selectPrcOrderBillByCustomerPeriod(query.getCustomerId(),
|
||||
@@ -332,7 +327,6 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
public BigDecimal sumPreviewBill(ArBillGenerateQuery query) {
|
||||
long startedAt = System.nanoTime();
|
||||
validatePreviewQuery(query);
|
||||
requireCustomerDataScope(query.getCustomerId());
|
||||
List<String> orderIdentifiers = normalizeOrderIdentifiers(query.getOrderOrTrackingNo());
|
||||
List<String> excludeOrderIdentifiers = normalizeOrderIdentifiers(query.getExcludeOrderOrTrackingNo());
|
||||
BigDecimal total = nvl(sourceBillMapper.sumPrcOrderBillIncomeByCustomerPeriod(query.getCustomerId(),
|
||||
@@ -356,13 +350,8 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
long startedAt = System.nanoTime();
|
||||
Long createUserId = SecurityUtils.getUserId();
|
||||
validatePeriod(request);
|
||||
requireCustomerDataScope(request.getCustomerId());
|
||||
ArBillGenerateTask existed = generateTaskMapper.selectByRequestToken(requestId);
|
||||
if (existed != null) {
|
||||
ArBill existedBill = requireBillDataScope(existed.getArBillId());
|
||||
if (!request.getCustomerId().equals(existedBill.getCustomerId())) {
|
||||
throw new ServiceException("请求标识已用于其他客户,请重新发起");
|
||||
}
|
||||
log.info("应收账单生成请求命中幂等记录,operator={}, requestId={}, taskId={}, status={}, costMs={}",
|
||||
safeLogValue(operator), safeLogValue(requestId), existed.getTaskId(), existed.getStatus(),
|
||||
elapsedMillis(startedAt));
|
||||
@@ -482,7 +471,6 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
if (task == null) {
|
||||
throw new ServiceException("账单生成任务不存在");
|
||||
}
|
||||
requireBillDataScope(task.getArBillId());
|
||||
log.debug("应收账单生成任务状态查询,taskId={}, status={}, processedCount={}, totalCount={}, costMs={}",
|
||||
taskId, task.getStatus(), task.getProcessedCount(), task.getTotalCount(), elapsedMillis(startedAt));
|
||||
return task;
|
||||
@@ -494,7 +482,7 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
@Override
|
||||
public List<ArBillGenerateTask> selectActiveGenerateTasks(String operator) {
|
||||
long startedAt = System.nanoTime();
|
||||
List<ArBillGenerateTask> tasks = dataScopeService.selectActiveGenerateTasks(new ArBillQuery(), operator);
|
||||
List<ArBillGenerateTask> tasks = generateTaskMapper.selectActiveByCreateBy(operator);
|
||||
log.debug("当前用户应收账单生成任务查询,operator={}, taskCount={}, costMs={}",
|
||||
safeLogValue(operator), tasks.size(), elapsedMillis(startedAt));
|
||||
return tasks;
|
||||
@@ -925,7 +913,6 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ArBill confirmBill(Long arBillId, ArBillActionRequest request, String operator, String requestId) {
|
||||
long startedAt = System.nanoTime();
|
||||
requireBillDataScope(arBillId);
|
||||
ArBill bill = billMapper.selectArBillByIdForUpdate(arBillId);
|
||||
if (bill == null) {
|
||||
throw failure(arBillId, ArLogObjectType.BILL, String.valueOf(arBillId), ArLogOperationType.CONFIRM,
|
||||
@@ -970,7 +957,6 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ArBill voidBill(Long arBillId, ArBillActionRequest request, String operator, String requestId) {
|
||||
long startedAt = System.nanoTime();
|
||||
requireBillDataScope(arBillId);
|
||||
String remark = request == null ? null : request.getRemark();
|
||||
if (StringUtils.isEmpty(remark)) {
|
||||
throw failure(arBillId, ArLogObjectType.BILL, String.valueOf(arBillId), ArLogOperationType.VOID,
|
||||
@@ -1015,22 +1001,23 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ArBillExport exportBill(Long arBillId, String operator, String requestId) {
|
||||
long startedAt = System.nanoTime();
|
||||
ArBill bill = requireBillDataScope(arBillId);
|
||||
Long exportUserId = SecurityUtils.getUserId();
|
||||
ArBillLog previous = logMapper.selectSuccessByRequestId(requestId, ArLogObjectType.EXPORT.getCode(),
|
||||
ArLogResult.SUCCESS.getCode());
|
||||
if (previous != null && isNumber(previous.getObjectId())) {
|
||||
ArBillExport previousExport = exportMapper.selectById(Long.valueOf(previous.getObjectId()));
|
||||
if (previousExport != null) {
|
||||
if (!arBillId.equals(previousExport.getArBillId())) {
|
||||
throw new ServiceException("请求标识已用于其他账单,请重新发起");
|
||||
}
|
||||
log.info("应收账单导出请求命中幂等记录,operator={}, requestId={}, arBillId={}, exportId={}, status={}, costMs={}",
|
||||
safeLogValue(operator), safeLogValue(requestId), arBillId, previousExport.getExportId(),
|
||||
previousExport.getExportStatus(), elapsedMillis(startedAt));
|
||||
return previousExport;
|
||||
}
|
||||
}
|
||||
ArBill bill = billMapper.selectArBillById(arBillId);
|
||||
if (bill == null) {
|
||||
throw failure(arBillId, ArLogObjectType.EXPORT, String.valueOf(arBillId), ArLogOperationType.EXPORT,
|
||||
null, "应收账单不存在", operator, requestId);
|
||||
}
|
||||
if (!ArBillGenerationStatus.READY.equals(bill.getGenerationStatus())) {
|
||||
throw failure(arBillId, ArLogObjectType.EXPORT, String.valueOf(arBillId), ArLogOperationType.EXPORT,
|
||||
bill.getStatus(), "账单尚未生成完成,暂不能导出", operator, requestId);
|
||||
@@ -1091,7 +1078,6 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
if (export == null) {
|
||||
throw new ServiceException("导出任务不存在");
|
||||
}
|
||||
requireBillDataScope(export.getArBillId());
|
||||
log.debug("应收账单导出任务状态查询,exportId={}, status={}, costMs={}",
|
||||
exportId, export.getExportStatus(), elapsedMillis(startedAt));
|
||||
return export;
|
||||
@@ -1172,7 +1158,6 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
@Override
|
||||
public List<ArBillExport> selectExports(Long arBillId) {
|
||||
long startedAt = System.nanoTime();
|
||||
requireBillDataScope(arBillId);
|
||||
List<ArBillExport> exports = exportMapper.selectByBillId(arBillId);
|
||||
log.debug("应收账单导出记录查询,arBillId={}, exportCount={}, costMs={}",
|
||||
arBillId, exports.size(), elapsedMillis(startedAt));
|
||||
@@ -1182,8 +1167,8 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
@Override
|
||||
public void downloadExport(Long exportId, HttpServletResponse response) throws Exception {
|
||||
long startedAt = System.nanoTime();
|
||||
ArBillExport export = selectExport(exportId);
|
||||
if (!ArExportStatus.SUCCESS.getCode().equals(export.getExportStatus()) || StringUtils.isEmpty(export.getStorageKey())) {
|
||||
ArBillExport export = exportMapper.selectById(exportId);
|
||||
if (export == null || !ArExportStatus.SUCCESS.getCode().equals(export.getExportStatus()) || StringUtils.isEmpty(export.getStorageKey())) {
|
||||
throw new ServiceException("导出文件不存在或尚未生成成功");
|
||||
}
|
||||
String resource = export.getStorageKey();
|
||||
@@ -1212,18 +1197,6 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
return logs;
|
||||
}
|
||||
|
||||
private ArBill requireBillDataScope(Long arBillId) {
|
||||
ArBillQuery query = new ArBillQuery();
|
||||
query.setArBillId(arBillId);
|
||||
return dataScopeService.requireBill(query);
|
||||
}
|
||||
|
||||
private void requireCustomerDataScope(Long customerId) {
|
||||
ArBillQuery query = new ArBillQuery();
|
||||
query.setCustomerId(customerId);
|
||||
dataScopeService.requireCustomer(query);
|
||||
}
|
||||
|
||||
private String exportFailureMessage(Exception e) {
|
||||
String message = StringUtils.isEmpty(e.getMessage()) ? "账单导出失败" : e.getMessage();
|
||||
return message.length() > 500 ? message.substring(0, 500) : message;
|
||||
|
||||
@@ -66,12 +66,6 @@
|
||||
<include refid="columns"/>
|
||||
where create_by = #{createBy}
|
||||
and status in ('WAITING', 'RUNNING', 'CANCEL_REQUESTED')
|
||||
<if test="params.dataScope != null and params.dataScope != ''">
|
||||
and exists (
|
||||
select 1 from ar_bill b where b.ar_bill_id = ar_bill_generate_task.ar_bill_id
|
||||
<include refid="com.bms.ar.mapper.ArBillMapper.customerDataScope"><property name="customerIdColumn" value="b.customer_id"/></include>
|
||||
)
|
||||
</if>
|
||||
order by create_time desc, task_id desc
|
||||
</select>
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<result property="createTime" column="create_time"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectList" resultMap="ArBillLogResult">
|
||||
<select id="selectList" parameterType="ArBillLog" resultMap="ArBillLogResult">
|
||||
select l.log_id, l.ar_bill_id, l.object_type, l.object_id, l.operation_type, l.operation_desc,
|
||||
case l.object_type
|
||||
when 'BILL' then b.bill_no
|
||||
@@ -43,15 +43,14 @@
|
||||
left join ar_balance_writeoff bw on bw.writeoff_id = case when l.object_type = 'BALANCE_WRITEOFF' then
|
||||
cast(l.object_id as unsigned) end
|
||||
<where>
|
||||
<if test="query.arBillId != null">and l.ar_bill_id = #{query.arBillId}</if>
|
||||
<if test="query.objectType != null and query.objectType != ''">and l.object_type = #{query.objectType}</if>
|
||||
<if test="query.objectId != null and query.objectId != ''">and l.object_id = #{query.objectId}</if>
|
||||
<if test="query.operationType != null and query.operationType != ''">and l.operation_type = #{query.operationType}</if>
|
||||
<if test="query.operationSource != null and query.operationSource != ''">and l.operation_source = #{query.operationSource}
|
||||
<if test="arBillId != null">and l.ar_bill_id = #{arBillId}</if>
|
||||
<if test="objectType != null and objectType != ''">and l.object_type = #{objectType}</if>
|
||||
<if test="objectId != null and objectId != ''">and l.object_id = #{objectId}</if>
|
||||
<if test="operationType != null and operationType != ''">and l.operation_type = #{operationType}</if>
|
||||
<if test="operationSource != null and operationSource != ''">and l.operation_source = #{operationSource}
|
||||
</if>
|
||||
<if test="query.requestId != null and query.requestId != ''">and l.request_id = #{query.requestId}</if>
|
||||
<if test="query.result != null and query.result != ''">and l.result = #{query.result}</if>
|
||||
<include refid="com.bms.ar.mapper.ArBillMapper.customerDataScope"><property name="customerIdColumn" value="b.customer_id"/></include>
|
||||
<if test="requestId != null and requestId != ''">and l.request_id = #{requestId}</if>
|
||||
<if test="result != null and result != ''">and l.result = #{result}</if>
|
||||
</where>
|
||||
order by l.create_time desc, l.log_id desc
|
||||
</select>
|
||||
|
||||
@@ -67,27 +67,6 @@
|
||||
from ar_bill
|
||||
</sql>
|
||||
|
||||
<!-- 仅受限角色增加 EXISTS,避免业务员历史关联产生重复账单和错误分页。
|
||||
sales_user_id 优先按用户ID解析;找不到ID时兼容历史工号,防止数字工号与用户ID同时匹配两个人。
|
||||
customerIdColumn 仅由下面各个 include 的固定属性传入。 -->
|
||||
<sql id="customerDataScope">
|
||||
<if test="params.dataScope != null and params.dataScope != ''">
|
||||
and exists (
|
||||
select 1 from ctr_customer ar_scope_customer
|
||||
left join sys_user ar_scope_id_user
|
||||
on ar_scope_customer.sales_user_id regexp '^[0-9]+$'
|
||||
and ar_scope_id_user.user_id = ar_scope_customer.sales_user_id + 0
|
||||
left join sys_user ar_scope_user
|
||||
on ar_scope_user.del_flag = '0'
|
||||
and (ar_scope_user.user_id = ar_scope_id_user.user_id
|
||||
or (ar_scope_id_user.user_id is null
|
||||
and ar_scope_user.user_name = ar_scope_customer.sales_user_id))
|
||||
where ar_scope_customer.customer_id = ${customerIdColumn}
|
||||
${params.dataScope}
|
||||
)
|
||||
</if>
|
||||
</sql>
|
||||
|
||||
<select id="selectArBillList" parameterType="com.bms.ar.domain.vo.ArBillQuery" resultMap="ArBillResult">
|
||||
<include refid="selectArBillColumns"/>
|
||||
<where>
|
||||
@@ -106,23 +85,10 @@
|
||||
<if test="billDateStart != null">and bill_date >= #{billDateStart}</if>
|
||||
<if test="billDateEnd != null">and bill_date <= #{billDateEnd}</if>
|
||||
<if test="billPeriodEnd != null">and bill_period_end = #{billPeriodEnd}</if>
|
||||
<include refid="customerDataScope"><property name="customerIdColumn" value="ar_bill.customer_id"/></include>
|
||||
</where>
|
||||
order by create_time desc, ar_bill_id desc
|
||||
</select>
|
||||
|
||||
<select id="selectArBillByDataScope" parameterType="com.bms.ar.domain.vo.ArBillQuery" resultMap="ArBillResult">
|
||||
<include refid="selectArBillColumns"/>
|
||||
where ar_bill_id = #{arBillId}
|
||||
<include refid="customerDataScope"><property name="customerIdColumn" value="ar_bill.customer_id"/></include>
|
||||
</select>
|
||||
|
||||
<select id="selectCustomerIdByDataScope" parameterType="com.bms.ar.domain.vo.ArBillQuery" resultType="long">
|
||||
select c.customer_id from ctr_customer c where c.customer_id = #{customerId}
|
||||
<include refid="customerDataScope"><property name="customerIdColumn" value="c.customer_id"/></include>
|
||||
</select>
|
||||
|
||||
<!-- 后台生成/导出任务使用原始查询,前台入口通过 selectArBillByDataScope 校验。 -->
|
||||
<select id="selectArBillById" parameterType="long" resultMap="ArBillResult">
|
||||
<include refid="selectArBillColumns"/>
|
||||
where ar_bill_id = #{arBillId}
|
||||
|
||||
Reference in New Issue
Block a user