Add bulk update functionality for destination data
- Introduced `DestinationMassUpdateDTO` to handle bulk update payload. - Added new API endpoint `/destination/all` for mass updates in `PremiseController`. - Updated frontend logic to support mass updating of destinations and enhanced matrix calculations with debounce. - Improved handling of destination and route processing across components.
This commit is contained in:
parent
a40a8c6bb4
commit
cbd467d3b0
8 changed files with 168 additions and 35 deletions
|
|
@ -107,7 +107,7 @@ export default {
|
|||
computed: {
|
||||
...mapStores(useDestinationEditStore, usePremiseEditStore),
|
||||
rows() {
|
||||
return this.destinationEditStore.getHandlingCostMatrix
|
||||
return this.destinationEditStore.getHandlingCostMatrix ?? [];
|
||||
},
|
||||
allChecked() {
|
||||
return this.rows.every(r => r.selected);
|
||||
|
|
@ -128,7 +128,10 @@ export default {
|
|||
async created() {
|
||||
this.onLoadingChange(true);
|
||||
try {
|
||||
await this.buildMatrix();
|
||||
await new Promise(resolve => setTimeout(() => {
|
||||
this.buildMatrix();
|
||||
resolve();
|
||||
}, 10));
|
||||
} finally {
|
||||
this.onLoadingChange(false);
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ export default {
|
|||
computed: {
|
||||
...mapStores(useDestinationEditStore, usePremiseEditStore),
|
||||
rows() {
|
||||
return this.destinationEditStore.getQuantityMatrix;
|
||||
return this.destinationEditStore.getQuantityMatrix ?? [];
|
||||
},
|
||||
allChecked() {
|
||||
return this.rows.every(r => r.selected);
|
||||
|
|
@ -98,7 +98,10 @@ export default {
|
|||
async created() {
|
||||
this.onLoadingChange(true);
|
||||
try {
|
||||
await this.buildMatrix();
|
||||
await new Promise(resolve => setTimeout(() => {
|
||||
this.buildMatrix();
|
||||
resolve();
|
||||
}, 10));
|
||||
} finally {
|
||||
this.onLoadingChange(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ export default {
|
|||
computed: {
|
||||
...mapStores(useDestinationEditStore, usePremiseEditStore),
|
||||
rows() {
|
||||
return this.destinationEditStore.getRouteMatrix;
|
||||
return this.destinationEditStore.getRouteMatrix ?? [];
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
|
@ -75,7 +75,10 @@ export default {
|
|||
async created() {
|
||||
this.onLoadingChange(true);
|
||||
try {
|
||||
await this.buildMatrix();
|
||||
await new Promise(resolve => setTimeout(() => {
|
||||
this.buildMatrix();
|
||||
resolve();
|
||||
}, 10));
|
||||
} finally {
|
||||
this.onLoadingChange(false);
|
||||
}
|
||||
|
|
@ -116,13 +119,16 @@ export default {
|
|||
const destOfCurPremise = this.destinationEditStore.getByPremiseId(pId);
|
||||
if (!destOfCurPremise) continue;
|
||||
|
||||
/* supplier map collects all destinations for one supplier
|
||||
* and replaces the destination if the same destination is found
|
||||
* that already has a selected route.
|
||||
/* supplier map collects all destinations for one supplier.
|
||||
* if there is more than one instance of a destination for one supplier
|
||||
* (more than one part number), a destination instance is chosen by the following priority list:
|
||||
* 1. instances with d2d rate
|
||||
* 2. instances with selected routes
|
||||
* 3. all other instances.
|
||||
*/
|
||||
if (!supplierToDestinationsMap.has(curPremise.supplier.id)) {
|
||||
supplierToDestinationsMap.set(curPremise.supplier.id, {
|
||||
destinations: destOfCurPremise ?? []
|
||||
destinations: [...destOfCurPremise]
|
||||
});
|
||||
} else {
|
||||
const mapEntry = supplierToDestinationsMap.get(curPremise.supplier.id);
|
||||
|
|
@ -144,8 +150,8 @@ export default {
|
|||
})
|
||||
}
|
||||
|
||||
/* destination map collects all destinations over all
|
||||
* suppliers for table headers
|
||||
/* Collects all destinations over all
|
||||
* suppliers and part numbers for the table headers
|
||||
*/
|
||||
for (const d of destOfCurPremise) {
|
||||
const destId = d.destination_node.id;
|
||||
|
|
@ -166,23 +172,23 @@ export default {
|
|||
const premiseMap = new Map();
|
||||
|
||||
this.premiseIds.forEach(pId => {
|
||||
const premise = this.premiseEditStore.getById(pId);
|
||||
const destinations = this.destinationEditStore.getByPremiseId(pId);
|
||||
const curPremise = this.premiseEditStore.getById(pId);
|
||||
const destOfCurPremise = this.destinationEditStore.getByPremiseId(pId);
|
||||
|
||||
if (!premiseMap.has(premise.supplier.id)) {
|
||||
premiseMap.set(premise.supplier.id, {
|
||||
if (!premiseMap.has(curPremise.supplier.id)) {
|
||||
premiseMap.set(curPremise.supplier.id, {
|
||||
ids: [],
|
||||
supplierNodeId: premise.supplier.id,
|
||||
supplier: premise.supplier,
|
||||
destinations: this.buildDestinations(columnHeadersMap, supplierToDestinationsMap.get(premise.supplier.id)?.destinations ?? [])
|
||||
supplierNodeId: curPremise.supplier.id,
|
||||
supplier: curPremise.supplier,
|
||||
destinations: this.buildDestinations(columnHeadersMap, supplierToDestinationsMap.get(curPremise.supplier.id)?.destinations ?? [])
|
||||
});
|
||||
}
|
||||
|
||||
const row = premiseMap.get(premise.supplier.id);
|
||||
const row = premiseMap.get(curPremise.supplier.id);
|
||||
|
||||
if (row) {
|
||||
row.ids.push(premise.id);
|
||||
this.addDestinationsToRow(row.destinations, destinations)
|
||||
row.ids.push(curPremise.id);
|
||||
this.addDestinationsToRow(row.destinations, destOfCurPremise)
|
||||
}
|
||||
|
||||
});
|
||||
|
|
@ -215,17 +221,25 @@ export default {
|
|||
}
|
||||
});
|
||||
},
|
||||
addDestinationsToRow(rowDestinations, premiseDestinations) {
|
||||
premiseDestinations.forEach(premD => {
|
||||
addDestinationsToRow(rowDestinations, destOfPremises) {
|
||||
destOfPremises.forEach(curDestOfPremise => {
|
||||
|
||||
let existingDest = rowDestinations.find(rowD => rowD.destinationNodeId === premD.destination_node.id) ?? null;
|
||||
/* rowDestinations contains all here known destinations that are shown
|
||||
*
|
||||
*
|
||||
*/
|
||||
let existingDest = rowDestinations.find(rowD => rowD.destinationNodeId === curDestOfPremise.destination_node.id) ?? null;
|
||||
|
||||
if (existingDest) {
|
||||
existingDest.disabled = false;
|
||||
existingDest.ids.push(premD.id);
|
||||
|
||||
if(existingDest.ids.includes(curDestOfPremise.id))
|
||||
console.log("Duplicate id: ", curDestOfPremise.id);
|
||||
|
||||
existingDest.ids.push(curDestOfPremise.id);
|
||||
|
||||
/* add route ids to routes */
|
||||
this.verifyRoutes(existingDest, premD)
|
||||
this.verifyRoutes(existingDest, curDestOfPremise)
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
@ -242,9 +256,13 @@ export default {
|
|||
premiseRoutes.forEach(route => {
|
||||
const routeString = JSON.stringify(route.transit_nodes.map(n => n.external_mapping_id)); //.join(" > ").replace("_", " ");
|
||||
|
||||
if (!(rowDest.routes.some(r => r.routeCompareString === routeString && r.type === route.type))) {
|
||||
const rowRoute = rowDest.routes.find(r => r.routeCompareString === routeString && r.type === route.type);
|
||||
|
||||
if (!rowRoute) {
|
||||
console.log("no matching route ", routeString, rowDest);
|
||||
rowDest.valid = false;
|
||||
} else {
|
||||
rowRoute.ids.push(route.id);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
@ -252,6 +270,7 @@ export default {
|
|||
|
||||
return routes?.map(r => {
|
||||
return {
|
||||
ids: [],
|
||||
type: r.type,
|
||||
selected: r.is_selected,
|
||||
transitNodes: r.transit_nodes.map(n => n.external_mapping_id),
|
||||
|
|
|
|||
|
|
@ -439,6 +439,8 @@ export default {
|
|||
},
|
||||
async closeEditModalAction(action) {
|
||||
|
||||
let massUpdate = false;
|
||||
|
||||
if (this.modalType === 'amount' || this.modalType === 'routes' || this.modalType === "destinations") {
|
||||
|
||||
if (action === 'accept') {
|
||||
|
|
@ -450,7 +452,7 @@ export default {
|
|||
await this.destinationEditStore.massSetDestinations(setMatrix);
|
||||
}
|
||||
} else {
|
||||
await this.destinationEditStore.massUpdateDestinations();
|
||||
massUpdate = true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -458,6 +460,10 @@ export default {
|
|||
this.fillData(this.modalType);
|
||||
this.modalType = null;
|
||||
|
||||
if(massUpdate) {
|
||||
await this.destinationEditStore.massUpdateDestinations(this.editIds);
|
||||
}
|
||||
|
||||
if (this.modalStash && action === 'accept') {
|
||||
setTimeout(() => {
|
||||
this.openModal(this.modalStash.type, this.modalStash.ids, this.modalStash.dataSource, this.modalStash.massEdit);
|
||||
|
|
|
|||
|
|
@ -108,15 +108,87 @@ export const useDestinationEditStore = defineStore('destinationEdit', {
|
|||
|
||||
this.loading = false;
|
||||
},
|
||||
async massUpdateDestinations() {
|
||||
async massUpdateDestinations(premiseIds) {
|
||||
this.loading = true;
|
||||
|
||||
this.updateQuantity();
|
||||
this.updateHandlingCosts();
|
||||
|
||||
await new Promise(resolve => setTimeout(() => {
|
||||
this.updateQuantity();
|
||||
resolve();
|
||||
}, 10));
|
||||
|
||||
await new Promise(resolve => setTimeout(() => {
|
||||
this.updateHandlingCosts();
|
||||
resolve();
|
||||
}, 10));
|
||||
|
||||
await new Promise(resolve => setTimeout(() => {
|
||||
this.updateRoutes();
|
||||
resolve();
|
||||
}, 10));
|
||||
|
||||
const destinationMap = new Map();
|
||||
|
||||
console.log("premiseids", premiseIds )
|
||||
|
||||
premiseIds.forEach(premiseId => {
|
||||
this.destinations.get(premiseId)?.forEach(toUpdate => {
|
||||
|
||||
console.log("toUpdate", toUpdate)
|
||||
|
||||
destinationMap.set(toUpdate.id,{
|
||||
annual_amount: toUpdate.annual_amount,
|
||||
repackaging_costs: toUpdate.repackaging_costs,
|
||||
handling_costs: toUpdate.handling_costs,
|
||||
disposal_costs: toUpdate.disposal_costs,
|
||||
is_d2d: toUpdate.is_d2d,
|
||||
rate_d2d: toUpdate.rate_d2d,
|
||||
lead_time_d2d: toUpdate.lead_time_d2d,
|
||||
route_selected_id: toUpdate.routes.find(r => r.is_selected)?.id ?? null,
|
||||
})
|
||||
} )
|
||||
});
|
||||
|
||||
console.log("destmap",destinationMap)
|
||||
|
||||
await performRequest(this, 'PUT', `${config.backendUrl}/calculation/destination/all`, {destinations: Object.fromEntries(destinationMap)}, false);
|
||||
|
||||
this.loading = false;
|
||||
},
|
||||
updateRoutes() {
|
||||
this.routeMatrix.forEach(row => {
|
||||
|
||||
row.ids.forEach(premiseId => {
|
||||
row.destinations.forEach(destinationUpdateInfo => {
|
||||
const destOfCurPremisses = this.destinations.get(premiseId);
|
||||
|
||||
if ((destOfCurPremisses ?? null) !== null) {
|
||||
const destOfCurPremise = destOfCurPremisses.find(d => destinationUpdateInfo.destinationNodeId === d.destination_node.id);
|
||||
|
||||
if(destinationUpdateInfo.ids.includes(destOfCurPremise.id)) {
|
||||
/* set d2d stuff */
|
||||
destOfCurPremise.is_d2d = destinationUpdateInfo.isD2d;
|
||||
destOfCurPremise.rate_d2d = destinationUpdateInfo.rateD2d;
|
||||
destOfCurPremise.lead_time_d2d = destinationUpdateInfo.leadTimeD2d;
|
||||
|
||||
/* set selected route */
|
||||
const selectedRoute = destinationUpdateInfo.routes?.find(r => r.routeCompareString === destinationUpdateInfo.selectedRoute);
|
||||
|
||||
destOfCurPremise.routes.forEach(r => r.is_selected = false);
|
||||
|
||||
if(selectedRoute) {
|
||||
const routeOfCurPremise = destOfCurPremise.routes.find(r => selectedRoute.ids.includes(r.id));
|
||||
|
||||
if(routeOfCurPremise) {
|
||||
routeOfCurPremise.is_selected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
updateHandlingCosts() {
|
||||
this.handlingCostMatrix.forEach(row => {
|
||||
const destinations = this.destinations.get(row.id);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import de.avatic.lcc.dto.calculation.create.CreatePremiseDTO;
|
|||
import de.avatic.lcc.dto.calculation.create.PremiseSearchResultDTO;
|
||||
import de.avatic.lcc.dto.calculation.edit.PremiseDetailDTO;
|
||||
import de.avatic.lcc.dto.calculation.edit.destination.DestinationCreateDTO;
|
||||
import de.avatic.lcc.dto.calculation.edit.destination.DestinationMassUpdateDTO;
|
||||
import de.avatic.lcc.dto.calculation.edit.destination.DestinationSetDTO;
|
||||
import de.avatic.lcc.dto.calculation.edit.destination.DestinationUpdateDTO;
|
||||
import de.avatic.lcc.dto.calculation.edit.masterData.MaterialUpdateDTO;
|
||||
|
|
@ -128,7 +129,8 @@ public class PremiseController {
|
|||
@GetMapping({"/edit", "/edit/"})
|
||||
@PreAuthorize("hasAnyRole('SUPER', 'CALCULATION')")
|
||||
public ResponseEntity<List<PremiseDetailDTO>> getPremises(@RequestParam List<Integer> premissIds) {
|
||||
return ResponseEntity.ok(premisesServices.getPremises(premissIds));
|
||||
var premisses = premisesServices.getPremises(premissIds);
|
||||
return ResponseEntity.ok(premisses);
|
||||
}
|
||||
|
||||
@PutMapping({"/start", "/start/"})
|
||||
|
|
@ -198,6 +200,13 @@ public class PremiseController {
|
|||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
@PutMapping({"/destination/all", "/destination/all/"})
|
||||
@PreAuthorize("hasAnyRole('SUPER', 'CALCULATION')")
|
||||
public ResponseEntity<Void> updateAllDestination(@RequestBody @Valid DestinationMassUpdateDTO destinationUpdateDTO) {
|
||||
destinationUpdateDTO.getDestinations().forEach(destinationService::updateDestination);
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
@DeleteMapping({"/destination/{id}", "/destination/{id}/"})
|
||||
@PreAuthorize("hasAnyRole('SUPER', 'CALCULATION')")
|
||||
public ResponseEntity<Void> deleteDestination(@PathVariable Integer id) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
package de.avatic.lcc.dto.calculation.edit.destination;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class DestinationMassUpdateDTO {
|
||||
|
||||
Map<Integer, @Valid DestinationUpdateDTO> destinations;
|
||||
|
||||
|
||||
public Map<Integer, DestinationUpdateDTO> getDestinations() {
|
||||
return destinations;
|
||||
}
|
||||
|
||||
public void setDestinations(Map<Integer, DestinationUpdateDTO> destinations) {
|
||||
this.destinations = destinations;
|
||||
}
|
||||
}
|
||||
|
|
@ -96,7 +96,9 @@ public class PremisesService {
|
|||
if (!admin)
|
||||
premiseRepository.checkOwner(premiseIds, userId);
|
||||
|
||||
return premiseRepository.getPremisesById(premiseIds).stream().filter(p -> p.getState().equals(PremiseState.DRAFT)).map(premiseTransformer::toPremiseDetailDTO).toList();
|
||||
var premisses = premiseRepository.getPremisesById(premiseIds).stream().filter(p -> p.getState().equals(PremiseState.DRAFT)).toList();
|
||||
|
||||
return premisses.stream().map(premiseTransformer::toPremiseDetailDTO).toList();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue