feat: Enhance Supply Chain Module with Analytic Move Line Features

- Added support for analytic move lines in InvoiceServiceSupplychainImpl.
- Implemented methods to check for missing analytic move lines in PurchaseOrderController and PurchaseRequestController.
- Introduced budget distribution line generation in PurchaseOrderController.
- Updated SaleOrderController to generate analytic move lines.
- Enhanced StockMoveController with budget distribution line generation.
- Modified StockMoveLineController to include analytic account and axis handling.
- Updated domain models to include references to analytic accounts and axes in Partner, StockLocation, and StockMoveLine.
- Created unit tests for StockMoveLineServiceSupplychainImpl to ensure proper functionality of new features.
- Added MockQuery class for testing purposes.
This commit is contained in:
BACHIR SOULDI
2026-02-17 15:13:17 +01:00
parent 9eb959f07a
commit 6881c439b2
74 changed files with 2975 additions and 930 deletions

View File

@@ -1,80 +1,76 @@
package com.axelor.apps.account.web;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
import com.axelor.apps.account.db.CashInventory;
import com.axelor.apps.base.service.ConvertNumberToFrenchWordsService;
import com.axelor.inject.Beans;
import com.axelor.rpc.ActionRequest;
import com.axelor.rpc.ActionResponse;
import static org.mockito.Mockito.*;
import org.mockito.ArgumentCaptor;
import static org.junit.Assert.assertEquals;
import java.math.BigDecimal;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
public class CashInventoryControllerTest {
private CashInventoryController controller;
private ActionRequest request;
private ActionResponse response;
private CashInventory cashInventory;
private ConvertNumberToFrenchWordsService convertService;
private CashInventoryController controller;
private ActionRequest request;
private ActionResponse response;
private CashInventory cashInventory;
private ConvertNumberToFrenchWordsService convertService;
@Before
public void setUp() {
request = mock(ActionRequest.class);
response = mock(ActionResponse.class);
cashInventory = mock(CashInventory.class);
convertService = mock(ConvertNumberToFrenchWordsService.class);
@Before
public void setUp() {
request = mock(ActionRequest.class);
response = mock(ActionResponse.class);
cashInventory = mock(CashInventory.class);
convertService = mock(ConvertNumberToFrenchWordsService.class);
controller = new CashInventoryController(convertService); // ✅ No Guice needed
controller = new CashInventoryController(convertService); // ✅ No Guice needed
// Mock request.getContext().asType(CashInventory.class)
com.axelor.rpc.Context context = mock(com.axelor.rpc.Context.class);
when(request.getContext()).thenReturn(context);
when(context.asType(CashInventory.class)).thenReturn(cashInventory);
}
// Mock request.getContext().asType(CashInventory.class)
com.axelor.rpc.Context context = mock(com.axelor.rpc.Context.class);
when(request.getContext()).thenReturn(context);
when(context.asType(CashInventory.class)).thenReturn(cashInventory);
}
@Test
public void testConvert_withDecimalSolde() {
// Given
when(cashInventory.getTheoricalSolde()).thenReturn(new BigDecimal("1234.56"));
when(convertService.convert(1234L)).thenReturn("mille deux cent trente-quatre");
when(convertService.convert(56L)).thenReturn("cinquante-six");
@Test
public void testConvert_withDecimalSolde() {
// Given
when(cashInventory.getTheoricalSolde()).thenReturn(new BigDecimal("1234.56"));
when(convertService.convert(1234L)).thenReturn("mille deux cent trente-quatre");
when(convertService.convert(56L)).thenReturn("cinquante-six");
}
}
@Test
public void testConvert_withIntegerSolde() {
// Given
when(cashInventory.getTheoricalSolde()).thenReturn(new BigDecimal("1000.00"));
when(convertService.convert(1000L)).thenReturn("mille");
when(convertService.convert(0L)).thenReturn("zéro");
@Test
public void testConvert_withIntegerSolde() {
// Given
when(cashInventory.getTheoricalSolde()).thenReturn(new BigDecimal("1000.00"));
when(convertService.convert(1000L)).thenReturn("mille");
when(convertService.convert(0L)).thenReturn("zéro");
// Then
ArgumentCaptor<String> keyCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<String> valueCaptor = ArgumentCaptor.forClass(String.class);
verify(response).setValue(keyCaptor.capture(), valueCaptor.capture());
assertEquals("theoricalSoldeInWords", keyCaptor.getValue());
assertEquals("mille dinars algériens et zéro Cts", valueCaptor.getValue());
}
// @Test
// public void testConvert_withNoDecimalPart() {
// // Given
// when(cashInventory.getTheoricalSolde()).thenReturn(new BigDecimal("42"));
// when(convertService.convert(42L)).thenReturn("quarante-deux");
// when(convertService.convert(0L)).thenReturn("zéro");
// Then
ArgumentCaptor<String> keyCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<String> valueCaptor = ArgumentCaptor.forClass(String.class);
verify(response).setValue(keyCaptor.capture(), valueCaptor.capture());
assertEquals("theoricalSoldeInWords", keyCaptor.getValue());
assertEquals("mille dinars algériens et zéro Cts", valueCaptor.getValue());
}
// @Test
// public void testConvert_withNoDecimalPart() {
// // Given
// when(cashInventory.getTheoricalSolde()).thenReturn(new BigDecimal("42"));
// when(convertService.convert(42L)).thenReturn("quarante-deux");
// when(convertService.convert(0L)).thenReturn("zéro");
// // Then
// ArgumentCaptor<String> keyCaptor = ArgumentCaptor.forClass(String.class);
// ArgumentCaptor<String> valueCaptor = ArgumentCaptor.forClass(String.class);
// verify(response).setValue(keyCaptor.capture(), valueCaptor.capture());
// assertEquals("theoricalSoldeInWords", keyCaptor.getValue());
// assertEquals("quarante-deux dinars algériens et zéro Cts",
// valueCaptor.getValue());
// }
}
// // Then
// ArgumentCaptor<String> keyCaptor = ArgumentCaptor.forClass(String.class);
// ArgumentCaptor<String> valueCaptor = ArgumentCaptor.forClass(String.class);
// verify(response).setValue(keyCaptor.capture(), valueCaptor.capture());
// assertEquals("theoricalSoldeInWords", keyCaptor.getValue());
// assertEquals("quarante-deux dinars algériens et zéro Cts",
// valueCaptor.getValue());
// }
}