mirror of
https://codeup.aliyun.com/67c68d4e484ca2f0a13ac3c1/ydc/jsowell-charger-web.git
synced 2026-07-23 15:41:17 +08:00
接入运营商提现开票待办闭环
This commit is contained in:
@@ -124,6 +124,9 @@ public class OrderService {
|
||||
@Autowired
|
||||
private ClearingWithdrawInfoService clearingWithdrawInfoService;
|
||||
|
||||
@Autowired
|
||||
private MerchantWithdrawInvoiceService merchantWithdrawInvoiceService;
|
||||
|
||||
@Autowired
|
||||
private MemberAdapayRecordService memberAdapayRecordService;
|
||||
|
||||
@@ -1464,22 +1467,7 @@ public class OrderService {
|
||||
log.info("取现成功 data:{}", JSON.toJSONString(data));
|
||||
JSONObject jsonObject = JSON.parseObject(data);
|
||||
String withdrawCode = jsonObject.getString("id");
|
||||
// 通过取现id查询取现数据
|
||||
ClearingWithdrawInfo clearingWithdrawInfo = clearingWithdrawInfoService.selectByWithdrawCode(withdrawCode);
|
||||
if (clearingWithdrawInfo != null) {
|
||||
clearingWithdrawInfo.setWithdrawStatus(Constants.ONE);
|
||||
clearingWithdrawInfo.setUpdateTime(DateUtils.getNowDate());
|
||||
clearingWithdrawInfoService.updateByPrimaryKeySelective(clearingWithdrawInfo);
|
||||
}
|
||||
|
||||
// 清分账单数据更新
|
||||
List<ClearingBillInfo> clearingBillInfos = clearingBillInfoService.selectByWithdrawCode(withdrawCode);
|
||||
if (CollectionUtils.isNotEmpty(clearingBillInfos)) {
|
||||
for (ClearingBillInfo clearingBillInfo : clearingBillInfos) {
|
||||
clearingBillInfo.setBillStatus("4");
|
||||
}
|
||||
clearingBillInfoService.updateBatchSelective(clearingBillInfos);
|
||||
}
|
||||
merchantWithdrawInvoiceService.handleWithdrawSucceeded(withdrawCode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.jsowell.web.controller.pile;
|
||||
|
||||
import com.jsowell.common.annotation.Log;
|
||||
import com.jsowell.common.core.controller.BaseController;
|
||||
import com.jsowell.common.core.domain.AjaxResult;
|
||||
import com.jsowell.common.enums.BusinessType;
|
||||
import com.jsowell.pile.dto.WithdrawInvoiceCloseRequest;
|
||||
import com.jsowell.pile.dto.WithdrawInvoiceSubmitRequest;
|
||||
import com.jsowell.pile.service.MerchantWithdrawInvoiceService;
|
||||
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.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 运营商提现向平台开票接口。
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/pile/withdrawInvoice")
|
||||
public class MerchantWithdrawInvoiceController extends BaseController {
|
||||
@Autowired
|
||||
private MerchantWithdrawInvoiceService merchantWithdrawInvoiceService;
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('system:todo:query')")
|
||||
@GetMapping("/{withdrawCode}")
|
||||
public AjaxResult getInfo(@PathVariable String withdrawCode, @RequestParam Long todoId) {
|
||||
return AjaxResult.success(merchantWithdrawInvoiceService.getForAssignee(
|
||||
withdrawCode, todoId, getUserId()));
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('system:todo:complete')")
|
||||
@Log(title = "运营商提现开票", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/{withdrawCode}/submit")
|
||||
public AjaxResult submit(@PathVariable String withdrawCode,
|
||||
@Validated @RequestBody WithdrawInvoiceSubmitRequest request) {
|
||||
return toAjax(merchantWithdrawInvoiceService.submit(withdrawCode, request,
|
||||
getUserId(), getUsername()));
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('system:todo:cancel')")
|
||||
@Log(title = "运营商提现开票", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/{withdrawCode}/close")
|
||||
public AjaxResult close(@PathVariable String withdrawCode,
|
||||
@Validated @RequestBody WithdrawInvoiceCloseRequest request) {
|
||||
return toAjax(merchantWithdrawInvoiceService.close(withdrawCode, request.getReason(),
|
||||
getUserId(), getUsername()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package com.jsowell.pile.service;
|
||||
|
||||
import com.jsowell.common.constant.Constants;
|
||||
import com.jsowell.pile.constant.MerchantWithdrawInvoiceConstants;
|
||||
import com.jsowell.pile.domain.ClearingBillInfo;
|
||||
import com.jsowell.pile.domain.ClearingWithdrawInfo;
|
||||
import com.jsowell.pile.domain.ClearingWithdrawInvoice;
|
||||
import com.jsowell.pile.domain.PileMerchantInfo;
|
||||
import com.jsowell.pile.dto.WithdrawInvoiceSubmitRequest;
|
||||
import com.jsowell.pile.mapper.ClearingWithdrawInfoMapper;
|
||||
import com.jsowell.pile.mapper.ClearingWithdrawInvoiceMapper;
|
||||
import com.jsowell.pile.service.impl.MerchantWithdrawInvoiceServiceImpl;
|
||||
import com.jsowell.system.domain.SysTodoTask;
|
||||
import com.jsowell.system.domain.dto.TodoTaskCreateCommand;
|
||||
import com.jsowell.system.service.TodoTaskAssigneeService;
|
||||
import com.jsowell.system.service.TodoTaskService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class MerchantWithdrawInvoiceServiceImplTest {
|
||||
@Test
|
||||
void handleSucceeded_shouldUpdateWithdrawAndCreateAdminTodos() {
|
||||
Dependencies dependencies = new Dependencies();
|
||||
MerchantWithdrawInvoiceServiceImpl service = dependencies.createService();
|
||||
ClearingWithdrawInfo withdrawInfo = withdrawInfo(Constants.ZERO);
|
||||
when(dependencies.withdrawInfoMapper.selectByWithdrawCode("W100")).thenReturn(withdrawInfo);
|
||||
when(dependencies.invoiceMapper.selectByWithdrawCode("W100")).thenReturn(null);
|
||||
when(dependencies.invoiceMapper.insertSelective(any(ClearingWithdrawInvoice.class))).thenReturn(1);
|
||||
ClearingBillInfo billInfo = new ClearingBillInfo();
|
||||
billInfo.setId(5);
|
||||
when(dependencies.clearingBillInfoService.selectByWithdrawCode("W100"))
|
||||
.thenReturn(Collections.singletonList(billInfo));
|
||||
PileMerchantInfo merchantInfo = new PileMerchantInfo();
|
||||
merchantInfo.setDeptId("200");
|
||||
when(dependencies.pileMerchantInfoService.selectPileMerchantInfoById(100L)).thenReturn(merchantInfo);
|
||||
when(dependencies.assigneeService.findActiveOperatorAdminUserIdsByDeptTree(200L))
|
||||
.thenReturn(Arrays.asList(8L, 9L));
|
||||
|
||||
service.handleWithdrawSucceeded("W100");
|
||||
|
||||
verify(dependencies.withdrawInfoMapper).updateByPrimaryKeySelective(withdrawInfo);
|
||||
assertEquals(Constants.ONE, withdrawInfo.getWithdrawStatus());
|
||||
assertEquals("4", billInfo.getBillStatus());
|
||||
verify(dependencies.clearingBillInfoService).updateBatchSelective(Collections.singletonList(billInfo));
|
||||
ArgumentCaptor<TodoTaskCreateCommand> captor = ArgumentCaptor.forClass(TodoTaskCreateCommand.class);
|
||||
verify(dependencies.todoTaskService, times(2)).createTask(captor.capture());
|
||||
assertEquals(Arrays.asList(8L, 9L), Arrays.asList(
|
||||
captor.getAllValues().get(0).getAssigneeUserId(),
|
||||
captor.getAllValues().get(1).getAssigneeUserId()));
|
||||
assertEquals(MerchantWithdrawInvoiceConstants.TASK_TYPE, captor.getValue().getTaskType());
|
||||
assertEquals(MerchantWithdrawInvoiceConstants.BUSINESS_TYPE, captor.getValue().getBusinessType());
|
||||
assertEquals("financeDetail", captor.getValue().getRouteName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void handleSucceeded_shouldNotRecreateTodoAfterInvoiceSubmitted() {
|
||||
Dependencies dependencies = new Dependencies();
|
||||
MerchantWithdrawInvoiceServiceImpl service = dependencies.createService();
|
||||
when(dependencies.withdrawInfoMapper.selectByWithdrawCode("W100"))
|
||||
.thenReturn(withdrawInfo(Constants.ONE));
|
||||
ClearingWithdrawInvoice invoice = invoice(MerchantWithdrawInvoiceConstants.STATUS_SUBMITTED);
|
||||
when(dependencies.invoiceMapper.selectByWithdrawCode("W100")).thenReturn(invoice);
|
||||
when(dependencies.clearingBillInfoService.selectByWithdrawCode("W100"))
|
||||
.thenReturn(Collections.emptyList());
|
||||
|
||||
service.handleWithdrawSucceeded("W100");
|
||||
|
||||
verify(dependencies.todoTaskService, never()).createTask(any(TodoTaskCreateCommand.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void submit_shouldCompleteAllBusinessTodos() {
|
||||
Dependencies dependencies = new Dependencies();
|
||||
MerchantWithdrawInvoiceServiceImpl service = dependencies.createService();
|
||||
when(dependencies.todoTaskService.getForAssignee(20L, 8L)).thenReturn(todoTask());
|
||||
when(dependencies.invoiceMapper.selectByWithdrawCode("W100"))
|
||||
.thenReturn(invoice(MerchantWithdrawInvoiceConstants.STATUS_PENDING));
|
||||
when(dependencies.invoiceMapper.markSubmitted(any(ClearingWithdrawInvoice.class))).thenReturn(1);
|
||||
WithdrawInvoiceSubmitRequest request = new WithdrawInvoiceSubmitRequest();
|
||||
request.setTodoId(20L);
|
||||
request.setInvoiceNumber("INV-100");
|
||||
request.setVoucherUrl("/profile/upload/invoice.pdf");
|
||||
|
||||
assertTrue(service.submit("W100", request, 8L, "operator"));
|
||||
|
||||
verify(dependencies.todoTaskService).completeByBusiness(
|
||||
MerchantWithdrawInvoiceConstants.BUSINESS_TYPE, "W100", null, 8L, "operator");
|
||||
}
|
||||
|
||||
@Test
|
||||
void close_shouldCancelAllBusinessTodos() {
|
||||
Dependencies dependencies = new Dependencies();
|
||||
MerchantWithdrawInvoiceServiceImpl service = dependencies.createService();
|
||||
when(dependencies.invoiceMapper.selectByWithdrawCode("W100"))
|
||||
.thenReturn(invoice(MerchantWithdrawInvoiceConstants.STATUS_PENDING));
|
||||
when(dependencies.invoiceMapper.markClosed(any(ClearingWithdrawInvoice.class))).thenReturn(1);
|
||||
|
||||
assertTrue(service.close("W100", "无需开票", 1L, "admin"));
|
||||
|
||||
verify(dependencies.todoTaskService).cancelByBusiness(
|
||||
MerchantWithdrawInvoiceConstants.BUSINESS_TYPE, "W100", null, "admin", "无需开票");
|
||||
}
|
||||
|
||||
private static ClearingWithdrawInfo withdrawInfo(String status) {
|
||||
ClearingWithdrawInfo withdrawInfo = new ClearingWithdrawInfo();
|
||||
withdrawInfo.setId(1);
|
||||
withdrawInfo.setMerchantId("100");
|
||||
withdrawInfo.setWithdrawCode("W100");
|
||||
withdrawInfo.setWithdrawStatus(status);
|
||||
return withdrawInfo;
|
||||
}
|
||||
|
||||
private static ClearingWithdrawInvoice invoice(String status) {
|
||||
ClearingWithdrawInvoice invoice = new ClearingWithdrawInvoice();
|
||||
invoice.setId(10L);
|
||||
invoice.setMerchantId("100");
|
||||
invoice.setWithdrawCode("W100");
|
||||
invoice.setInvoiceStatus(status);
|
||||
return invoice;
|
||||
}
|
||||
|
||||
private static SysTodoTask todoTask() {
|
||||
SysTodoTask task = new SysTodoTask();
|
||||
task.setTodoId(20L);
|
||||
task.setTaskType(MerchantWithdrawInvoiceConstants.TASK_TYPE);
|
||||
task.setBusinessType(MerchantWithdrawInvoiceConstants.BUSINESS_TYPE);
|
||||
task.setBusinessId("W100");
|
||||
task.setTaskStatus("PENDING");
|
||||
return task;
|
||||
}
|
||||
|
||||
private static void setField(Object target, String fieldName, Object value) {
|
||||
try {
|
||||
Field field = MerchantWithdrawInvoiceServiceImpl.class.getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
field.set(target, value);
|
||||
} catch (Exception exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Dependencies {
|
||||
private final ClearingWithdrawInfoMapper withdrawInfoMapper = mock(ClearingWithdrawInfoMapper.class);
|
||||
private final ClearingWithdrawInvoiceMapper invoiceMapper = mock(ClearingWithdrawInvoiceMapper.class);
|
||||
private final ClearingBillInfoService clearingBillInfoService = mock(ClearingBillInfoService.class);
|
||||
private final PileMerchantInfoService pileMerchantInfoService = mock(PileMerchantInfoService.class);
|
||||
private final TodoTaskAssigneeService assigneeService = mock(TodoTaskAssigneeService.class);
|
||||
private final TodoTaskService todoTaskService = mock(TodoTaskService.class);
|
||||
|
||||
private MerchantWithdrawInvoiceServiceImpl createService() {
|
||||
MerchantWithdrawInvoiceServiceImpl service = new MerchantWithdrawInvoiceServiceImpl();
|
||||
setField(service, "clearingWithdrawInfoMapper", withdrawInfoMapper);
|
||||
setField(service, "clearingWithdrawInvoiceMapper", invoiceMapper);
|
||||
setField(service, "clearingBillInfoService", clearingBillInfoService);
|
||||
setField(service, "pileMerchantInfoService", pileMerchantInfoService);
|
||||
setField(service, "todoTaskAssigneeService", assigneeService);
|
||||
setField(service, "todoTaskService", todoTaskService);
|
||||
return service;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.jsowell.web.controller.pile;
|
||||
|
||||
import com.jsowell.common.core.domain.AjaxResult;
|
||||
import com.jsowell.pile.dto.WithdrawInvoiceSubmitRequest;
|
||||
import com.jsowell.pile.service.MerchantWithdrawInvoiceService;
|
||||
import com.jsowell.pile.vo.web.MerchantWithdrawInvoiceVO;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class MerchantWithdrawInvoiceControllerTest {
|
||||
@Test
|
||||
void getInfo_shouldUseCurrentLoginUser() {
|
||||
MerchantWithdrawInvoiceService service = mock(MerchantWithdrawInvoiceService.class);
|
||||
TestController controller = newController(service, 8L, "operator");
|
||||
MerchantWithdrawInvoiceVO view = new MerchantWithdrawInvoiceVO();
|
||||
when(service.getForAssignee("W100", 20L, 8L)).thenReturn(view);
|
||||
|
||||
AjaxResult result = controller.getInfo("W100", 20L);
|
||||
|
||||
assertSame(view, result.get(AjaxResult.DATA_TAG));
|
||||
verify(service).getForAssignee("W100", 20L, 8L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void submit_shouldPassCurrentUserAndOperator() {
|
||||
MerchantWithdrawInvoiceService service = mock(MerchantWithdrawInvoiceService.class);
|
||||
TestController controller = newController(service, 8L, "operator");
|
||||
WithdrawInvoiceSubmitRequest request = new WithdrawInvoiceSubmitRequest();
|
||||
request.setTodoId(20L);
|
||||
request.setInvoiceNumber("INV-100");
|
||||
request.setVoucherUrl("/invoice.pdf");
|
||||
when(service.submit("W100", request, 8L, "operator")).thenReturn(true);
|
||||
|
||||
controller.submit("W100", request);
|
||||
|
||||
verify(service).submit("W100", request, 8L, "operator");
|
||||
}
|
||||
|
||||
private static TestController newController(MerchantWithdrawInvoiceService service,
|
||||
Long userId, String username) {
|
||||
TestController controller = new TestController(userId, username);
|
||||
try {
|
||||
Field field = MerchantWithdrawInvoiceController.class
|
||||
.getDeclaredField("merchantWithdrawInvoiceService");
|
||||
field.setAccessible(true);
|
||||
field.set(controller, service);
|
||||
} catch (Exception exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
return controller;
|
||||
}
|
||||
|
||||
private static class TestController extends MerchantWithdrawInvoiceController {
|
||||
private final Long userId;
|
||||
private final String username;
|
||||
|
||||
private TestController(Long userId, String username) {
|
||||
this.userId = userId;
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user