2 Commits

Author SHA1 Message Date
Kheireddine Mehdi
936c00cda4 fix(crm): prevent infinite loop when StateAdministration parent is itself 2026-03-10 09:20:00 +01:00
Kheireddine Mehdi
55e9f4455c feat: add StateAdministration entity and extend Address with state relation
- Create StateAdministration entity with hierarchical parent relation
- Add typeSelect selection (Region, Sub Region, Wilaya, Commune)
- Implement computed fullName for hierarchical display
- Extend Address entity with many-to-one relation to StateAdministration
2026-03-03 12:03:54 +01:00
4 changed files with 135 additions and 63 deletions

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="base" package="com.axelor.apps.base.db" />
<entity name="Address" lang="java">
<many-to-one name="state" ref="com.axelor.apps.crm.db.StateAdministration" title="State" />
</entity>
</domain-models>

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<domain-models xmlns="http://axelor.com/xml/ns/domain-models"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://axelor.com/xml/ns/domain-models http://axelor.com/xml/ns/domain-models/domain-models_5.2.xsd">
<module name="crm" package="com.axelor.apps.crm.db"/>
<entity name="StateAdministration" lang="java">
<string name="name" title="Name" required="true"/>
<string name="typeSelect" title="Type" selection="state.administration.type.select" required="true"/>
<many-to-one name="parent" ref="com.axelor.apps.crm.db.StateAdministration"/>
<string name="fullName" namecolumn="true" title="Full name">
<![CDATA[
String fullName = "";
com.axelor.apps.crm.db.StateAdministration current = this;
while (current != null && current.getName() != null) {
if (current == current.getParent()) {
break;
}
if (fullName.isEmpty()) {
fullName = current.getName();
} else {
fullName = current.getName() + " - " + fullName;
}
current = current.getParent();
}
return fullName;
]]>
</string>
</entity>
</domain-models>

View File

@@ -143,4 +143,11 @@
<option value="1">Some user groups</option>
</selection>
<selection name="state.administration.type.select">
<option value="0">Region</option>
<option value="1">Sub Region</option>
<option value="2">Wilaya</option>
<option value="3">Commune</option>
</selection>
</object-views>

View File

@@ -93,7 +93,7 @@ public class StockMoveInvoiceServiceImpl implements StockMoveInvoiceService {
}
@Override
@Transactional(rollbackOn = { Exception.class })
@Transactional(rollbackOn = {Exception.class})
public Invoice createInvoice(
StockMove stockMove,
Integer operationSelect,
@@ -130,7 +130,8 @@ public class StockMoveInvoiceServiceImpl implements StockMoveInvoiceService {
if (StockMoveRepository.ORIGIN_SALE_ORDER.equals(stockMove.getOriginTypeSelect())) {
invoice = createInvoiceFromSaleOrder(stockMove, saleOrderRepo.find(origin), qtyToInvoiceMap);
} else if (StockMoveRepository.ORIGIN_PURCHASE_ORDER.equals(stockMove.getOriginTypeSelect())) {
invoice = createInvoiceFromPurchaseOrder(
invoice =
createInvoiceFromPurchaseOrder(
stockMove, purchaseOrderRepo.find(origin), qtyToInvoiceMap);
} else {
invoice = createInvoiceFromOrderlessStockMove(stockMove, qtyToInvoiceMap);
@@ -146,7 +147,8 @@ public class StockMoveInvoiceServiceImpl implements StockMoveInvoiceService {
for (StockMoveLine subLine : stockMoveLine.getSubLineList()) {
BigDecimal qty = BigDecimal.ZERO;
if (stockMoveLine.getQty().compareTo(BigDecimal.ZERO) != 0) {
qty = qtyToInvoiceItem
qty =
qtyToInvoiceItem
.multiply(subLine.getQty())
.divide(stockMoveLine.getQty(), 2, RoundingMode.HALF_EVEN);
}
@@ -157,13 +159,13 @@ public class StockMoveInvoiceServiceImpl implements StockMoveInvoiceService {
}
@Override
@Transactional(rollbackOn = { Exception.class })
@Transactional(rollbackOn = {Exception.class})
public Invoice createInvoiceFromSaleOrder(
StockMove stockMove, SaleOrder saleOrder, Map<Long, BigDecimal> qtyToInvoiceMap)
throws AxelorException {
InvoiceGenerator invoiceGenerator = saleOrderInvoiceService.createInvoiceGenerator(saleOrder,
stockMove.getIsReversion());
InvoiceGenerator invoiceGenerator =
saleOrderInvoiceService.createInvoiceGenerator(saleOrder, stockMove.getIsReversion());
Invoice invoice = invoiceGenerator.generate();
@@ -208,12 +210,13 @@ public class StockMoveInvoiceServiceImpl implements StockMoveInvoiceService {
}
@Override
@Transactional(rollbackOn = { Exception.class })
@Transactional(rollbackOn = {Exception.class})
public Invoice createInvoiceFromPurchaseOrder(
StockMove stockMove, PurchaseOrder purchaseOrder, Map<Long, BigDecimal> qtyToInvoiceMap)
throws AxelorException {
InvoiceGenerator invoiceGenerator = purchaseOrderInvoiceService.createInvoiceGenerator(
InvoiceGenerator invoiceGenerator =
purchaseOrderInvoiceService.createInvoiceGenerator(
purchaseOrder, stockMove.getIsReversion());
Invoice invoice = invoiceGenerator.generate();
@@ -246,7 +249,7 @@ public class StockMoveInvoiceServiceImpl implements StockMoveInvoiceService {
}
@Override
@Transactional(rollbackOn = { Exception.class })
@Transactional(rollbackOn = {Exception.class})
public Invoice createInvoiceFromOrderlessStockMove(
StockMove stockMove, Map<Long, BigDecimal> qtyToInvoiceMap) throws AxelorException {
@@ -271,7 +274,8 @@ public class StockMoveInvoiceServiceImpl implements StockMoveInvoiceService {
}
}
InvoiceGenerator invoiceGenerator = new InvoiceGeneratorSupplyChain(stockMove, invoiceOperationType) {
InvoiceGenerator invoiceGenerator =
new InvoiceGeneratorSupplyChain(stockMove, invoiceOperationType) {
@Override
public Invoice generate() throws AxelorException {
@@ -336,10 +340,12 @@ public class StockMoveInvoiceServiceImpl implements StockMoveInvoiceService {
Long id = stockMoveLine.getId();
if (qtyToInvoiceMap != null) {
if (qtyToInvoiceMap.containsKey(id)) {
invoiceLineListCreated = this.createInvoiceLine(invoice, stockMoveLine, qtyToInvoiceMap.get(id));
invoiceLineListCreated =
this.createInvoiceLine(invoice, stockMoveLine, qtyToInvoiceMap.get(id));
}
} else {
invoiceLineListCreated = this.createInvoiceLine(
invoiceLineListCreated =
this.createInvoiceLine(
invoice,
stockMoveLine,
stockMoveLine.getRealQty().subtract(stockMoveLine.getQtyInvoiced()));
@@ -418,7 +424,8 @@ public class StockMoveInvoiceServiceImpl implements StockMoveInvoiceService {
stockMoveLine.getStockMove().getStockMoveSeq());
}
InvoiceLineGenerator invoiceLineGenerator = new InvoiceLineGeneratorSupplyChain(
InvoiceLineGenerator invoiceLineGenerator =
new InvoiceLineGeneratorSupplyChain(
invoice,
product,
stockMoveLine.getProductName(),
@@ -458,8 +465,7 @@ public class StockMoveInvoiceServiceImpl implements StockMoveInvoiceService {
}
/**
* Get a list of stock move lines consolidated by parent line (sale or purchase
* order).
* Get a list of stock move lines consolidated by parent line (sale or purchase order).
*
* @param stockMoveLineList
* @return
@@ -490,9 +496,7 @@ public class StockMoveInvoiceServiceImpl implements StockMoveInvoiceService {
stockMoveLinePurchaseMap.put(stockMoveLine.getPurchaseOrderLine(), list);
}
list.add(stockMoveLine);
resultList.add(stockMoveLine);
} else { // if the stock move line does not have a parent line (sale or purchase order
// line)
} else { // if the stock move line does not have a parent line (sale or purchase order line)
resultList.add(stockMoveLine);
}
}
@@ -540,12 +544,14 @@ public class StockMoveInvoiceServiceImpl implements StockMoveInvoiceService {
stockMove = Beans.get(StockMoveRepository.class).find(stockMove.getId());
if (stockMove.getInvoiceSet() != null && !stockMove.getInvoiceSet().isEmpty()) {
Double totalInvoicedQty = stockMove
Double totalInvoicedQty =
stockMove
.getStockMoveLineList()
.stream()
.mapToDouble(sml -> Double.parseDouble(sml.getQtyInvoiced().toString()))
.sum();
Double totalRealQty = stockMove
Double totalRealQty =
stockMove
.getStockMoveLineList()
.stream()
.mapToDouble(sml -> Double.parseDouble(sml.getRealQty().toString()))