Merge pull request 'Implement Warehouse....' (#47) from feature/intern_warehouse into master
Reviewed-by: Jannik Seiler <seil0@mosad.xyz>
This commit is contained in:
commit
6317780dfa
|
@ -0,0 +1,73 @@
|
|||
package org.hso.ecommerce.action.warehouse;
|
||||
|
||||
import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
public class CalculateWarehouseStatsAction {
|
||||
|
||||
private List<WarehouseBookingPositionSlotEntry> entryList;
|
||||
|
||||
public CalculateWarehouseStatsAction(List<WarehouseBookingPositionSlotEntry> everyCurrentEntry) {
|
||||
this.entryList = everyCurrentEntry;
|
||||
}
|
||||
|
||||
public WarehouseStats finish() {
|
||||
int numArticles = calculateNumArticles();
|
||||
double efficiency = calculateEfficiency();
|
||||
double ratioUsedSlots = calculateRatioSlotsUsed();
|
||||
|
||||
return new WarehouseStats(numArticles, efficiency, ratioUsedSlots);
|
||||
}
|
||||
|
||||
private double calculateRatioSlotsUsed() {
|
||||
int used = 0;
|
||||
|
||||
for (WarehouseBookingPositionSlotEntry entry : entryList) {
|
||||
if (entry.newSumSlot > 0) {
|
||||
used++;
|
||||
}
|
||||
}
|
||||
|
||||
return ((double) used) / entryList.size();
|
||||
}
|
||||
|
||||
private double calculateEfficiency() {
|
||||
double e = 0;
|
||||
|
||||
for (WarehouseBookingPositionSlotEntry entry : entryList) {
|
||||
if (entry.newSumSlot > 0) {
|
||||
e += entry.newSumSlot / (double) entry.article.warehouseUnitsPerSlot;
|
||||
} else {
|
||||
e += 0;
|
||||
}
|
||||
}
|
||||
|
||||
return e / entryList.size();
|
||||
}
|
||||
|
||||
private int calculateNumArticles() {
|
||||
HashSet<Long> articleIds = new HashSet<>();
|
||||
|
||||
for (WarehouseBookingPositionSlotEntry entry : entryList) {
|
||||
if (entry.newSumSlot > 0) {
|
||||
articleIds.add(entry.article.id);
|
||||
}
|
||||
}
|
||||
|
||||
return articleIds.size();
|
||||
}
|
||||
|
||||
private static class WarehouseStats {
|
||||
public int numArticles;
|
||||
public double efficiency;
|
||||
public double ratioUsedSlots;
|
||||
|
||||
WarehouseStats(int numArticles, double efficiency, double ratioUsedSlots) {
|
||||
this.numArticles = numArticles;
|
||||
this.efficiency = efficiency;
|
||||
this.ratioUsedSlots = ratioUsedSlots;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package org.hso.ecommerce.action.warehouse;
|
||||
|
||||
import org.hso.ecommerce.entities.booking.BookingReason;
|
||||
import org.hso.ecommerce.entities.shop.Article;
|
||||
import org.hso.ecommerce.entities.warehouse.WarehouseBooking;
|
||||
import org.hso.ecommerce.entities.warehouse.WarehouseBookingPosition;
|
||||
import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
|
||||
public class CreateManuelBookingAction {
|
||||
|
||||
private Article article;
|
||||
private int amount;
|
||||
private Optional<WarehouseBookingPositionSlotEntry> source;
|
||||
private Optional<WarehouseBookingPositionSlotEntry> destination;
|
||||
private String reason;
|
||||
|
||||
public CreateManuelBookingAction(Article article, int amount, Optional<WarehouseBookingPositionSlotEntry> source, Optional<WarehouseBookingPositionSlotEntry> destination, String reason) {
|
||||
this.article = article;
|
||||
this.amount = amount;
|
||||
this.source = source;
|
||||
this.destination = destination;
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public WarehouseBooking finish() throws ArticleSlotConstraintFailedException {
|
||||
WarehouseBooking booking = new WarehouseBooking();
|
||||
booking.created = new Timestamp(new Date().getTime());
|
||||
booking.reason = new BookingReason(reason);
|
||||
|
||||
if (source.isPresent()) {
|
||||
|
||||
if (source.get().article.id != article.id) {
|
||||
throw new ArticleSlotConstraintArticleTypeFailedException();
|
||||
}
|
||||
|
||||
WarehouseBookingPosition bookingPosition = new WarehouseBookingPosition();
|
||||
bookingPosition.booking = booking;
|
||||
|
||||
bookingPosition.article = article;
|
||||
bookingPosition.amount = -amount;
|
||||
bookingPosition.slotEntry = source.get().copyAddAmount(-amount);
|
||||
|
||||
if (bookingPosition.slotEntry.newSumSlot < 0 || bookingPosition.slotEntry.newSumSlot > article.warehouseUnitsPerSlot) {
|
||||
throw new ArticleSlotConstraintFailedException("The quantity of article can only be set in bounds.");
|
||||
}
|
||||
|
||||
booking.positions.add(bookingPosition);
|
||||
}
|
||||
|
||||
if (destination.isPresent()) {
|
||||
|
||||
if (destination.get().article.id != article.id) {
|
||||
throw new ArticleSlotConstraintArticleTypeFailedException();
|
||||
}
|
||||
|
||||
WarehouseBookingPosition bookingPosition = new WarehouseBookingPosition();
|
||||
bookingPosition.booking = booking;
|
||||
|
||||
bookingPosition.article = article;
|
||||
bookingPosition.amount = amount;
|
||||
bookingPosition.slotEntry = destination.get().copyAddAmount(amount);
|
||||
|
||||
if (bookingPosition.slotEntry.newSumSlot < 0 || bookingPosition.slotEntry.newSumSlot > article.warehouseUnitsPerSlot) {
|
||||
throw new ArticleSlotConstraintFailedException("The quantity of article can only be set in bounds.");
|
||||
}
|
||||
|
||||
booking.positions.add(bookingPosition);
|
||||
}
|
||||
|
||||
return booking;
|
||||
}
|
||||
|
||||
public static class ArticleSlotConstraintFailedException extends Exception {
|
||||
public ArticleSlotConstraintFailedException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public ArticleSlotConstraintFailedException() {
|
||||
super("The quantity of article can only be set in bounds.");
|
||||
}
|
||||
}
|
||||
|
||||
public static class ArticleSlotConstraintArticleTypeFailedException extends ArticleSlotConstraintFailedException {
|
||||
public ArticleSlotConstraintArticleTypeFailedException() {
|
||||
super("The Article in the slot entry does not match.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -119,39 +119,4 @@ public class RequestController {
|
|||
public String accountingAddManual() {
|
||||
return "intern/accounting/addManual";
|
||||
}
|
||||
|
||||
@GetMapping("/intern/warehouse/")
|
||||
public String accountingWarehouse() {
|
||||
return "intern/warehouse/index";
|
||||
}
|
||||
|
||||
@GetMapping("/intern/warehouse/todo")
|
||||
public String accountingWarehouseTodo() {
|
||||
return "intern/warehouse/todo";
|
||||
}
|
||||
|
||||
@GetMapping("/intern/warehouse/addManual")
|
||||
public String accountingWarehouseAddManual() {
|
||||
return "intern/warehouse/addManual";
|
||||
}
|
||||
|
||||
@PostMapping("/intern/warehouse/progress/{id}")
|
||||
public String accountingWarehouseProgressIdPost(HttpServletResponse response) {
|
||||
if ((notSoRandom++) % 2 == 1) {
|
||||
return "redirect:/intern/warehouse/progress/450";
|
||||
} else {
|
||||
response.setStatus(409);
|
||||
return "intern/warehouse/error_progress_failed";
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/intern/warehouse/progress/{id}")
|
||||
public String accountingWarehouseProgressId() {
|
||||
return "intern/warehouse/id_progress";
|
||||
}
|
||||
|
||||
@GetMapping("/intern/warehouse/slots/")
|
||||
public String accountingWarehouseSlots() {
|
||||
return "intern/warehouse/slots/index";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,27 @@
|
|||
package org.hso.ecommerce.controller.intern;
|
||||
|
||||
import org.hso.ecommerce.repos.warehouse.WarehouseBookingRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@Controller
|
||||
//@RequestMapping("...")
|
||||
@RequestMapping("/intern/warehouse/")
|
||||
public class WarehouseController {
|
||||
|
||||
@Autowired
|
||||
private final WarehouseBookingRepository warehouseBookingRepository = null;
|
||||
|
||||
@GetMapping("/")
|
||||
public String accountingWarehouse(
|
||||
Model model,
|
||||
HttpServletRequest request
|
||||
) {
|
||||
model.addAttribute("bookings", warehouseBookingRepository.findAll());
|
||||
return "intern/warehouse/index";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
package org.hso.ecommerce.controller.intern.warehouse;
|
||||
|
||||
import org.hso.ecommerce.action.warehouse.CreateManuelBookingAction;
|
||||
import org.hso.ecommerce.entities.shop.Article;
|
||||
import org.hso.ecommerce.entities.warehouse.Slot;
|
||||
import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry;
|
||||
import org.hso.ecommerce.repos.shop.ArticleRepository;
|
||||
import org.hso.ecommerce.repos.warehouse.SlotRepository;
|
||||
import org.hso.ecommerce.repos.warehouse.WarehouseBookingPositionSlotEntryRepository;
|
||||
import org.hso.ecommerce.repos.warehouse.WarehouseBookingRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Optional;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/intern/warehouse/")
|
||||
public class ManuelBookingController {
|
||||
|
||||
@Autowired
|
||||
private final ArticleRepository articleRepository = null;
|
||||
|
||||
@Autowired
|
||||
private final SlotRepository slotRepository = null;
|
||||
|
||||
@Autowired
|
||||
private final WarehouseBookingPositionSlotEntryRepository warehouseBookingPositionSlotEntryRepository = null;
|
||||
|
||||
@Autowired
|
||||
private final WarehouseBookingRepository warehouseBookingRepository = null;
|
||||
|
||||
@GetMapping("addManual")
|
||||
public String warehouseAddManual(
|
||||
Model model
|
||||
) {
|
||||
|
||||
model.addAttribute("articles", articleRepository.findAll());
|
||||
model.addAttribute("slots", slotRepository.findAll());
|
||||
|
||||
return "intern/warehouse/addManual";
|
||||
}
|
||||
|
||||
@PostMapping("addManual")
|
||||
public String warehouseAddMaualPost(
|
||||
Model model,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
@RequestParam("articleId") String articleIdText,
|
||||
@RequestParam("amount") Integer amount,
|
||||
@RequestParam("reason") String reason,
|
||||
@RequestParam("sourceIsSlot") Boolean sourceIsSlot,
|
||||
@RequestParam("sourceSlot") Integer sourceSlotNum,
|
||||
@RequestParam("destinationIsSlot") Boolean destinationIsSlot,
|
||||
@RequestParam("destinationSlot") Integer destinationSlotNum
|
||||
) {
|
||||
|
||||
// The suggestions for articleId in the UI show articles names, seperated by a " - ".
|
||||
// The Number must be extracted first.
|
||||
long articleId = -1;
|
||||
try {
|
||||
articleId = Long.parseLong(articleIdText.split(" - ", 2)[0].trim());
|
||||
} catch (NumberFormatException e) {
|
||||
model.addAttribute("error", "Die Artikel Id konnte nicht erkannt werden.");
|
||||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return "intern/warehouse/addManual";
|
||||
}
|
||||
|
||||
|
||||
Optional<Article> optionalArticle = articleRepository.findById(articleId);
|
||||
Article article = null;
|
||||
if (!optionalArticle.isPresent()) {
|
||||
model.addAttribute("error", "Der Artikel konnte nicht gefunden werden.");
|
||||
response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
|
||||
return "intern/warehouse/addManual";
|
||||
} else {
|
||||
article = optionalArticle.get();
|
||||
}
|
||||
|
||||
if (amount <= 0) {
|
||||
model.addAttribute("error", "Eine Anzahl <= 0 kann nicht verbucht werden.");
|
||||
response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
|
||||
return "intern/warehouse/addManual";
|
||||
}
|
||||
|
||||
if (sourceIsSlot == false && destinationIsSlot == false) {
|
||||
model.addAttribute("error", "Jede Buchung benötigt ein Ziel oder eine Quelle.");
|
||||
response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
|
||||
return "intern/warehouse/addManual";
|
||||
}
|
||||
|
||||
Optional<WarehouseBookingPositionSlotEntry> sourceSlot = Optional.empty();
|
||||
if (sourceIsSlot == true) {
|
||||
sourceSlot = warehouseBookingPositionSlotEntryRepository.getBySlotNum(sourceSlotNum);
|
||||
if (!sourceSlot.isPresent()) {
|
||||
request.setAttribute("error", "Quelllagerplatz wurde nicht gefunden oder ist leer.");
|
||||
response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
|
||||
return "intern/warehouse/addManual";
|
||||
}
|
||||
}
|
||||
|
||||
Optional<WarehouseBookingPositionSlotEntry> destinationSlot = Optional.empty();
|
||||
if (destinationIsSlot == true) {
|
||||
Optional<Slot> slot = slotRepository.findBySlotNum(destinationSlotNum);
|
||||
if (!slot.isPresent()) {
|
||||
request.setAttribute("error", "Ziellagerplatz wurde nicht gefunden.");
|
||||
response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
|
||||
return "intern/warehouse/addManual";
|
||||
}
|
||||
|
||||
Article finalArticle = article;
|
||||
destinationSlot = Optional.of(warehouseBookingPositionSlotEntryRepository.getBySlotNum(destinationSlotNum).orElseGet(
|
||||
() -> WarehouseBookingPositionSlotEntry.empty(finalArticle, slot.get())
|
||||
));
|
||||
}
|
||||
|
||||
try {
|
||||
warehouseBookingRepository.save(
|
||||
new CreateManuelBookingAction(article, amount, sourceSlot, destinationSlot, reason).finish()
|
||||
);
|
||||
} catch (CreateManuelBookingAction.ArticleSlotConstraintArticleTypeFailedException e) {
|
||||
model.addAttribute("error", "Es befindet sich der falsche Artikeltyp in Quell- oder Ziellagerplatz. ");
|
||||
response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
|
||||
return "intern/warehouse/addManual";
|
||||
} catch (CreateManuelBookingAction.ArticleSlotConstraintFailedException e) {
|
||||
model.addAttribute("error", "Die maximale Anzahl an lagerbaren Artikeln im Ziellagerplatz wurde überschritten.");
|
||||
response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
|
||||
return "intern/warehouse/addManual";
|
||||
}
|
||||
|
||||
return "redirect:/intern/warehouse/todo";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package org.hso.ecommerce.controller.intern.warehouse;
|
||||
|
||||
import org.hso.ecommerce.action.warehouse.CalculateWarehouseStatsAction;
|
||||
import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry;
|
||||
import org.hso.ecommerce.repos.warehouse.SlotRepository;
|
||||
import org.hso.ecommerce.repos.warehouse.WarehouseBookingPositionSlotEntryRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/intern/warehouse/")
|
||||
public class SlotsController {
|
||||
|
||||
@Autowired
|
||||
private final WarehouseBookingPositionSlotEntryRepository warehouseBookingPositionSlotEntryRepository = null;
|
||||
|
||||
@Autowired
|
||||
private final SlotRepository slotRepository = null;
|
||||
|
||||
@GetMapping("slots/")
|
||||
public String accountingWarehouseSlots(
|
||||
Model model,
|
||||
HttpServletRequest request
|
||||
) {
|
||||
|
||||
// Doing this in a single would be hard and error prone.
|
||||
// Writing native queries should be minimized.
|
||||
// Therefore this method was prefered
|
||||
List<WarehouseBookingPositionSlotEntry> entries = slotRepository.findAll().stream().map(
|
||||
s -> warehouseBookingPositionSlotEntryRepository
|
||||
.getBySlotNum(s.slotNum)
|
||||
.orElseGet(() -> WarehouseBookingPositionSlotEntry.empty(null, s))
|
||||
).collect(Collectors.toList());
|
||||
model.addAttribute("entries", entries);
|
||||
|
||||
model.addAttribute("stats", new CalculateWarehouseStatsAction(entries).finish());
|
||||
return "intern/warehouse/slots/index";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
package org.hso.ecommerce.controller.intern.warehouse;
|
||||
|
||||
import org.hso.ecommerce.action.shop.EnableTrackingAction;
|
||||
import org.hso.ecommerce.entities.warehouse.WarehouseBooking;
|
||||
import org.hso.ecommerce.repos.warehouse.WarehouseBookingRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Optional;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/intern/warehouse/")
|
||||
public class TodoController {
|
||||
|
||||
@Autowired
|
||||
private final WarehouseBookingRepository warehouseBookingRepository = null;
|
||||
|
||||
@GetMapping("todo")
|
||||
public String accountingWarehouseTodo(
|
||||
Model model
|
||||
) {
|
||||
model.addAttribute("bookings", warehouseBookingRepository.findNotDone());
|
||||
return "intern/warehouse/todo";
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("progress/{id}")
|
||||
public String postProgressId(
|
||||
Model model,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
@PathVariable("id") Long id
|
||||
) {
|
||||
Optional<WarehouseBooking> booking = warehouseBookingRepository.findById(id);
|
||||
if (!booking.isPresent()) {
|
||||
model.addAttribute("error", "Die Buchung wurde nicht gefunden.");
|
||||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return "error/404";
|
||||
}
|
||||
|
||||
if (booking.get().isInProgress) {
|
||||
response.setStatus(409);
|
||||
return "intern/warehouse/error_progress_failed";
|
||||
}
|
||||
|
||||
booking.get().isInProgress = true;
|
||||
warehouseBookingRepository.save(booking.get());
|
||||
|
||||
return "redirect:/intern/warehouse/progress/" + id;
|
||||
}
|
||||
|
||||
@PostMapping("progress/{id}/finish")
|
||||
public String postProgressIdFinish(
|
||||
Model model,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
@PathVariable("id") Long id
|
||||
) {
|
||||
Optional<WarehouseBooking> booking = warehouseBookingRepository.findById(id);
|
||||
if (!booking.isPresent()) {
|
||||
model.addAttribute("error", "Die Buchung wurde nicht gefunden.");
|
||||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return "error/404";
|
||||
}
|
||||
|
||||
booking.get().isInProgress = true;
|
||||
booking.get().isDone = true;
|
||||
|
||||
// Update Delivery Date
|
||||
if (booking.get().reason.customerOrder != null) {
|
||||
EnableTrackingAction.addTrackingInfo(booking.get().reason.customerOrder);
|
||||
}
|
||||
|
||||
warehouseBookingRepository.save(booking.get());
|
||||
|
||||
return "redirect:/intern/warehouse/todo";
|
||||
}
|
||||
|
||||
@GetMapping("progress/{id}")
|
||||
public String getProgressId(Model model,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
@PathVariable("id") Long id) {
|
||||
Optional<WarehouseBooking> booking = warehouseBookingRepository.findById(id);
|
||||
if (!booking.isPresent()) {
|
||||
model.addAttribute("error", "Die Buchung wurde nicht gefunden.");
|
||||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return "error/404";
|
||||
}
|
||||
|
||||
if (booking.get().isDone) {
|
||||
model.addAttribute("info", "Die Buchung wurde schon abgeschlossen.");
|
||||
}
|
||||
|
||||
if (!booking.get().isInProgress) {
|
||||
// Only reachable if path is manipulated.
|
||||
model.addAttribute("error", "Die Buchung wurde noch nicht zugewiesen!");
|
||||
}
|
||||
|
||||
model.addAttribute("booking", booking.get());
|
||||
return "intern/warehouse/id_progress";
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package org.hso.ecommerce.controller.shop;
|
||||
|
||||
import org.hso.ecommerce.action.shop.CreateOrderAction;
|
||||
import org.hso.ecommerce.action.shop.EnableTrackingAction;
|
||||
import org.hso.ecommerce.entities.booking.BookingAccountEntry;
|
||||
import org.hso.ecommerce.entities.booking.PaymentMethod;
|
||||
import org.hso.ecommerce.entities.shop.Address;
|
||||
|
@ -136,7 +135,6 @@ public class ShopCheckoutController {
|
|||
CreateOrderAction.Result result = null;
|
||||
try {
|
||||
result = action.finish();
|
||||
EnableTrackingAction.addTrackingInfo(result.customerOrder);
|
||||
|
||||
customerOderRepository.save(result.customerOrder);
|
||||
bookingRepository.saveAll(result.bookings);
|
||||
|
|
|
@ -43,4 +43,9 @@ public class BookingReason {
|
|||
public BookingReason(SupplierOrder supplierOrder) {
|
||||
this.supplierOrder = supplierOrder;
|
||||
}
|
||||
|
||||
public BookingReason(String comment) {
|
||||
this.isManuel = true;
|
||||
this.comment = comment;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public class CustomerOrder {
|
|||
@NotNull
|
||||
public java.sql.Timestamp created;
|
||||
|
||||
@NotNull
|
||||
@Column(nullable = true)
|
||||
public String trackingId;
|
||||
|
||||
@Column(nullable = true)
|
||||
|
|
|
@ -38,4 +38,14 @@ public class WarehouseBookingPositionSlotEntry {
|
|||
|
||||
return e;
|
||||
}
|
||||
|
||||
public static WarehouseBookingPositionSlotEntry empty(Article article, Slot slot) {
|
||||
WarehouseBookingPositionSlotEntry e = new WarehouseBookingPositionSlotEntry();
|
||||
|
||||
e.article = article;
|
||||
e.slot = slot;
|
||||
e.newSumSlot = 0;
|
||||
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,10 +13,12 @@ public interface WarehouseBookingPositionSlotEntryRepository extends JpaReposito
|
|||
|
||||
@Query(value = "Select e.id, e.article_id, e.new_sum_slot, e.slot_id from warehouse_booking_position_entries as e, warehouse_slots as s where e.slot_id = s.id AND e.article_id = :article GROUP BY s.slot_num HAVING max(e.id)", nativeQuery = true)
|
||||
List<WarehouseBookingPositionSlotEntry> getByArticle(long article);
|
||||
|
||||
|
||||
|
||||
@Query(value = "SELECT SUM(w.new_sum_slot) FROM warehouse_booking_position_entries as w WHERE w.article_id = :articleid", nativeQuery = true)
|
||||
Optional<Integer> getArticleStock(long articleid);
|
||||
|
||||
|
||||
@Query(value = "Select e.id, e.article_id, e.new_sum_slot, e.slot_id from warehouse_booking_position_entries as e, warehouse_slots as s where e.slot_id = s.id AND s.slot_num = :slotnum GROUP BY s.slot_num HAVING max(e.id)", nativeQuery = true)
|
||||
Optional<WarehouseBookingPositionSlotEntry> getBySlotNum(long slotnum);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -2,10 +2,16 @@ package org.hso.ecommerce.repos.warehouse;
|
|||
|
||||
import org.hso.ecommerce.entities.warehouse.WarehouseBooking;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface WarehouseBookingRepository extends JpaRepository<WarehouseBooking, Long> {
|
||||
|
||||
@Query("Select b FROM WarehouseBooking b WHERE b.isDone = 0")
|
||||
List<WarehouseBooking> findNotDone();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -20,14 +20,12 @@
|
|||
<main class="sidebar-layout content-width">
|
||||
<nav th:replace="fragments/intern :: sidebar"></nav>
|
||||
<div class="content-width">
|
||||
<form class="detailgrid" th:action="@{/intern/warehouse/todo}">
|
||||
<form class="detailgrid" method="post" th:action="@{/intern/warehouse/addManual}">
|
||||
<div class="m">
|
||||
<label for="amount">Artikelnummer</label>
|
||||
<input placeholder="Nr." class="full-width" type="text" name="article" value="" list="articles"/>
|
||||
<input placeholder="Nr." class="full-width" type="text" name="articleId" value="" list="articles"/>
|
||||
<datalist id="articles">
|
||||
<option value="5100 - Kamera"/>
|
||||
<option value="5200 - Usb Stick"/>
|
||||
<option value="5640 - Stativ"/>
|
||||
<option th:each="article: ${articles}" th:value="${article.id + ' - ' + article.title}"/>
|
||||
</datalist>
|
||||
</div>
|
||||
<div class="s">
|
||||
|
@ -36,20 +34,23 @@
|
|||
</div>
|
||||
<div class="l">
|
||||
<label for="reason">Grund:</label>
|
||||
<input placeholder="Grund" class="full-width" type="text" name="reason-man" value=""/>
|
||||
<input placeholder="Grund" class="full-width" type="text" name="reason" value=""/>
|
||||
</div>
|
||||
|
||||
<div class="s">
|
||||
<fieldset>
|
||||
<label for="source">Von</label>
|
||||
<fieldset>
|
||||
<input type="radio" id="s-no" name="source" value="None" required>
|
||||
<input type="radio" id="s-no" name="sourceIsSlot" value="false" required>
|
||||
<label for="s-no">Hinzufügen</label>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<input type="radio" id="s-main" name="source" value="Slot" required>
|
||||
<input type="radio" id="s-main" name="sourceIsSlot" value="true" required>
|
||||
<label for="s-main">Lagerplatz</label>
|
||||
<input placeholder="Nr." type="text" name="source-slot" value=""/>
|
||||
<input placeholder="Nr." type="text" name="sourceSlot" value="" list="slots"/>
|
||||
<datalist id="slots">
|
||||
<option th:each="slot: ${slots}" th:value="${slot.slotNum}"/>
|
||||
</datalist>
|
||||
</fieldset>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
@ -58,13 +59,13 @@
|
|||
<fieldset>
|
||||
<label for="destination">Nach</label>
|
||||
<fieldset>
|
||||
<input type="radio" id="d-no" name="destination" value="None" required>
|
||||
<input type="radio" id="d-no" name="destinationIsSlot" value="false" required>
|
||||
<label for="d-no">Entfernen</label>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<input type="radio" id="d-main" name="destination" value="Main" required>
|
||||
<input type="radio" id="d-main" name="destinationIsSlot" value="true" required>
|
||||
<label for="d-main">Lagerplatz</label>
|
||||
<input placeholder="Nr." type="text" name="destination-slot" value=""/>
|
||||
<input placeholder="Nr." type="text" name="destinationSlot" value="" list="slots"/>
|
||||
</fieldset>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
|
|
@ -21,35 +21,54 @@
|
|||
</tr>
|
||||
|
||||
<!-------------------------------------------------------------->
|
||||
<tr data-group="3">
|
||||
<td>2020-01-12 12:18</td>
|
||||
<td colspan="4" class="l">
|
||||
<a th:href="@{/intern/customerOrders/4808}">Bestellung 8408</a>
|
||||
<div>
|
||||
Hans Maier <br/>
|
||||
Hauptstraße 12<br/>
|
||||
74880 Musterstadt<br/>
|
||||
Deutschland <br/>
|
||||
</div>
|
||||
<tr>
|
||||
<td th:text="${booking.created.toString()}"></td>
|
||||
<td th:if="${booking.reason.isManuel}" colspan="4" class="l">
|
||||
Manuell:
|
||||
<pre th:text="${booking.reason.comment}"></pre>
|
||||
</td>
|
||||
<td th:if="${booking.reason.isStartBooking}" colspan="4" class="l">
|
||||
Startbuchung
|
||||
</td>
|
||||
<td th:if="${booking.reason.customerOrder != null}" colspan="4" class="l">
|
||||
<a th:href="${'/intern/customerOrders/' + booking.reason.customerOrder.id}">
|
||||
Bestellung: <span th:text="${booking.reason.customerOrder.id}"></span>
|
||||
</a>
|
||||
<pre th:text="${booking.reason.customerOrder.destination.toString()}"></pre>
|
||||
</td>
|
||||
<td th:if="${booking.reason.supplierOrder != null}" colspan="4" class="l">
|
||||
<a th:href="${'/intern/supplierOrders/#q=' + booking.reason.supplierOrder.id}">
|
||||
Lieferung: <span th:text="${booking.reason.supplierOrder.id}"></span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr data-group="3">
|
||||
<td><img th:src="@{/img/product-1.jpg}" class="s"/></td>
|
||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
||||
<td>1</td>
|
||||
<td><a th:href="@{/intern/warehouse/slots/#q=%231}">Lagerplatz 01</a></td>
|
||||
<td> -</td>
|
||||
</tr>
|
||||
<tr data-group="3">
|
||||
<td><img th:src="@{/img/product-2.jpg}" class="s"/></td>
|
||||
<td><a th:href="@{/intern/listedArticles/4205}">Spielzeugauto</a></td>
|
||||
<td>2</td>
|
||||
<td><a th:href="@{/intern/warehouse/slots/#q=%232}">Lagerplatz 02</a></td>
|
||||
<td> -</td>
|
||||
<tr th:each="pos : ${booking.positions}">
|
||||
<td><img th:src="@{/shop/articles/{id}/image.jpg(id=${pos.article.id})}" class="s"/></td>
|
||||
<td><a th:href="@{/intern/articles/{id}(id=${pos.article.id})}"
|
||||
th:text="${pos.article.title}"></a></td>
|
||||
<th:block th:if="${pos.amount > 0}">
|
||||
<td th:text="${pos.amount}"></td>
|
||||
<td> -</td>
|
||||
<td><a th:href="${'/intern/warehouse/slots/#q=%23' + pos.slotEntry.slot.slotNum}">Lagerplatz <span
|
||||
th:text="${pos.slotEntry.slot.slotNum}"></span> </a></td>
|
||||
</th:block>
|
||||
<th:block th:if="${pos.amount < 0}">
|
||||
<td th:text="${pos.amount * -1}"></td>
|
||||
<td><a th:href="${'/intern/warehouse/slots/#q=%23' + pos.slotEntry.slot.slotNum}">Lagerplatz <span
|
||||
th:text="${pos.slotEntry.slot.slotNum}"></span> </a></td>
|
||||
<td> -</td>
|
||||
</th:block>
|
||||
<th:block th:if="${pos.amount == 0}">
|
||||
<td th:text="${pos.amount}"></td>
|
||||
<td> -</td>
|
||||
<td> -</td>
|
||||
</th:block>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
<a class="secondary button" th:href="@{/intern/warehouse/todo}"> Abschließen </a>
|
||||
<form method="post" th:action="@{/intern/warehouse/progress/{id}/finish(id=${booking.id})}">
|
||||
<button class="secondary full-width"> Abschließen</button>
|
||||
</form>
|
||||
</div>
|
||||
</main>
|
||||
<footer th:replace="fragments/footer :: footer"></footer>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="de" dir="ltr" xmlns:th="http://www.thymeleaf.org">
|
||||
<html dir="ltr" lang="de" xmlns:th="http://www.thymeleaf.org">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.75, user-scalable=no">
|
||||
<meta content="width=device-width, initial-scale=0.75, user-scalable=no" name="viewport">
|
||||
|
||||
<title>Lager</title>
|
||||
<script th:src="@{/js/filterTable.js}"></script>
|
||||
|
@ -18,7 +18,7 @@
|
|||
<h1>Lagerbuchungen</h1>
|
||||
|
||||
<script th:src="@{/js/back.js}"></script>
|
||||
<div class="back" data-group="intern" data-name="Zurück zu den Lagerbuchungen." data-insert="false"></div>
|
||||
<div class="back" data-group="intern" data-insert="false" data-name="Zurück zu den Lagerbuchungen."></div>
|
||||
</div>
|
||||
</div>
|
||||
<main class="sidebar-layout content-width">
|
||||
|
@ -32,8 +32,8 @@
|
|||
<table id="main-table">
|
||||
<tr>
|
||||
<th colspan="7">
|
||||
<input type="text" placeholder="Filtern" class="smaller jsFilterTable full-width"
|
||||
data-target-id="main-table"></input>
|
||||
<input class="smaller jsFilterTable full-width" data-target-id="main-table" placeholder="Filtern"
|
||||
type="text"></input>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -45,77 +45,61 @@
|
|||
<th>Status</th>
|
||||
</tr>
|
||||
|
||||
<th:block th:each="booking : ${bookings}">
|
||||
<tr th:data-group="${booking.id}">
|
||||
<td th:text="${booking.created.toString()}"></td>
|
||||
<td class="l" colspan="4" th:if="${booking.reason.isManuel}">
|
||||
Manuell: <small th:text="${booking.reason.comment}"></small>
|
||||
</td>
|
||||
<td class="l" colspan="4" th:if="${booking.reason.isStartBooking}">
|
||||
Startbuchung
|
||||
</td>
|
||||
<td class="l" colspan="4" th:if="${booking.reason.customerOrder != null}">
|
||||
<a th:href="${'/intern/customerOrders/' + booking.reason.customerOrder.id}">
|
||||
Bestellung: <span th:text="${booking.reason.customerOrder.id}"></span>
|
||||
</a>
|
||||
</td>
|
||||
<td class="l" colspan="4" th:if="${booking.reason.supplierOrder != null}">
|
||||
<a th:href="${'/intern/supplierOrders/#q=' + booking.reason.supplierOrder.id}">
|
||||
Lieferung: <span th:text="${booking.reason.supplierOrder.id}"></span>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<!-------------------------------------------------------------->
|
||||
<tr data-group="3">
|
||||
<td>2020-01-12 12:18</td>
|
||||
<td colspan="4" class="l">
|
||||
<a th:href="@{/intern/customerOrders/4808}">Bestellung 8408</a>
|
||||
</td>
|
||||
<td>Auf Warteliste <br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr data-group="3">
|
||||
<td></td>
|
||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
||||
<td>1</td>
|
||||
<td><a th:href="@{/intern/warehouse/slots/#q=%231}">Lagerplatz 01</a></td>
|
||||
<td> -</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr data-group="3">
|
||||
<td></td>
|
||||
<td><a th:href="@{/intern/listedArticles/4205}">Spielzeugauto</a></td>
|
||||
<td>2</td>
|
||||
<td><a th:href="@{/intern/warehouse/slots/#q=%232}">Lagerplatz 02</a></td>
|
||||
<td> -</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<td th:if="${!booking.isInProgress && !booking.isDone}">
|
||||
Auf Warteliste
|
||||
</td>
|
||||
<td th:if="${booking.isInProgress && !booking.isDone}">
|
||||
Wird bearbeitet
|
||||
</td>
|
||||
<td th:if="${booking.isInProgress && booking.isDone}">
|
||||
Fertig
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-------------------------------------------------------------->
|
||||
<tr data-group="2">
|
||||
<td>2020-01-12 12:15</td>
|
||||
<td colspan="4" class="l">
|
||||
Manuell: Ware war defekt.
|
||||
</td>
|
||||
<td>In Arbeit <br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr data-group="2">
|
||||
<td></td>
|
||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
||||
<td>1</td>
|
||||
<td><a th:href="@{/intern/warehouse/slots/#q=%231}">Lagerplatz 01</a></td>
|
||||
<td> -</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!-------------------------------------------------------------->
|
||||
<tr data-group="1">
|
||||
<td>2020-01-12 12:11</td>
|
||||
<td colspan="4" class="l">
|
||||
<a th:href="@{/intern/supplierOrders/#q=4545}">Lieferung 4545</a>
|
||||
</td>
|
||||
<td>Fertig <br/></td>
|
||||
</tr>
|
||||
<tr data-group="1">
|
||||
<td></td>
|
||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
||||
<td>10</td>
|
||||
<td> -</td>
|
||||
<td><a th:href="@{/intern/warehouse/slots/#q=%231}">Lagerplatz 01</a>
|
||||
</th>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr data-group="1">
|
||||
<td></td>
|
||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
||||
<td>1</td>
|
||||
<td> -</td>
|
||||
<td><a th:href="@{/intern/warehouse/slots/#q=%234}">Lagerplatz 04</a></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr th:data-group="${booking.id}" th:each="pos : ${booking.positions}">
|
||||
<td></td>
|
||||
<td><a th:href="@{/intern/articles/{id}(id=${pos.article.id})}"
|
||||
th:text="${pos.article.title}"></a></td>
|
||||
<th:block th:if="${pos.amount > 0}">
|
||||
<td th:text="${pos.amount}"></td>
|
||||
<td> -</td>
|
||||
<td><a th:href="${'/intern/warehouse/slots/#q=%23' + pos.slotEntry.slot.slotNum}">Lagerplatz
|
||||
<span th:text="${pos.slotEntry.slot.slotNum}"></span> </a></td>
|
||||
</th:block>
|
||||
<th:block th:if="${pos.amount < 0}">
|
||||
<td th:text="${pos.amount * -1}"></td>
|
||||
<td><a th:href="${'/intern/warehouse/slots/#q=%23' + pos.slotEntry.slot.slotNum}">Lagerplatz
|
||||
<span th:text="${pos.slotEntry.slot.slotNum}"></span> </a></td>
|
||||
<td> -</td>
|
||||
</th:block>
|
||||
<th:block th:if="${pos.amount == 0}">
|
||||
<td th:text="${pos.amount}"></td>
|
||||
<td> -</td>
|
||||
<td> -</td>
|
||||
</th:block>
|
||||
<td></td>
|
||||
</tr>
|
||||
</th:block>
|
||||
|
||||
</table>
|
||||
</p>
|
||||
|
|
|
@ -27,15 +27,16 @@
|
|||
<!-- Dirty -->
|
||||
<div style="min-width: 10rem; display: inline-block; margin: var(--u0);">
|
||||
<h3>Plätze in Verwendung</h3>
|
||||
<h2>67%</h2>
|
||||
<h2><span th:text="${#numbers.formatDecimal(stats.ratioUsedSlots * 100, 2, 'POINT', 2, 'COMMA')}"></span>%
|
||||
</h2>
|
||||
</div>
|
||||
<div style="min-width: 10rem; display: inline-block; margin: var(--u0);">
|
||||
<h3>Lagereffizienz</h3>
|
||||
<h2>43%</h2>
|
||||
<h2><span th:text="${#numbers.formatDecimal(stats.efficiency * 100, 2, 'POINT', 2, 'COMMA')}"></span>%</h2>
|
||||
</div>
|
||||
<div style="min-width: 10rem; display: inline-block; margin: var(--u0);">
|
||||
<h3>Lagerdiversität</h3>
|
||||
<h2>3</h2>
|
||||
<h2><span th:text="${stats.numArticles}"></span></h2>
|
||||
</div>
|
||||
<p>
|
||||
<table id="main-table">
|
||||
|
@ -52,47 +53,21 @@
|
|||
<th>Anzahl</th>
|
||||
<th>Max.</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><h2>#1</h2></td>
|
||||
<td><img th:src="@{/img/product-1.jpg}" class="s"/></td>
|
||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
||||
<td>20</td>
|
||||
<td>20</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><h2>#2</h2></td>
|
||||
<td><img th:src="@{/img/product-1.jpg}" class="s"/></td>
|
||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
||||
<td>1</td>
|
||||
<td>20</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><h2>#3</h2></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><h2>#4</h2></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>0</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><h2>#5</h2></td>
|
||||
<td><img th:src="@{/img/product-3.jpg}" class="s"/></td>
|
||||
<td><a th:href="@{/intern/listedArticles/45015}">Usb-Ding</a></td>
|
||||
<td>1</td>
|
||||
<td>10</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><h2>#6</h2></td>
|
||||
<td><img th:src="@{/img/product-4.jpg}" class="s"/></td>
|
||||
<td><a th:href="@{/intern/listedArticles/45015}">Stativ</a></td>
|
||||
<td>3</td>
|
||||
<td>5</td>
|
||||
<tr th:each="entry : ${entries}">
|
||||
<td><h3>#<span th:text="${entry.slot.slotNum}"></span></h3></td>
|
||||
<th:block th:if="${entry.newSumSlot > 0}">
|
||||
<td><img th:src="@{/shop/articles/{id}/image.jpg(id=${entry.article.id})}" class="xs"/></td>
|
||||
<td><a th:href="@{/intern/articles/{id}(id=${entry.article.id})}" th:text="${entry.article.title}"
|
||||
class="s"/></td>
|
||||
<td th:text="${entry.newSumSlot}"></td>
|
||||
<td th:text="${entry.article.warehouseUnitsPerSlot}"></td>
|
||||
</th:block>
|
||||
<th:block th:if="${entry.newSumSlot == 0}">
|
||||
<td></td>
|
||||
<td> -</td>
|
||||
<td> .</td>
|
||||
<td></td>
|
||||
</th:block>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
<main class="sidebar-layout content-width">
|
||||
<nav th:replace="fragments/intern :: sidebar"></nav>
|
||||
<div class="content-width">
|
||||
<h2 th:if="${bookings.size() == 0}">Es gibt keine offenen Lagerbuchungen!</h2>
|
||||
<p>
|
||||
<table id="main-table">
|
||||
<tr>
|
||||
|
@ -41,60 +42,63 @@
|
|||
<th>Status</th>
|
||||
</tr>
|
||||
|
||||
<th:block th:each="booking : ${bookings}">
|
||||
<tr th:data-group="${booking.id}">
|
||||
<td th:text="${booking.created.toString()}"></td>
|
||||
<td th:if="${booking.reason.isManuel}" colspan="4" class="l">
|
||||
Manuell:
|
||||
<pre th:text="${booking.reason.comment}"></pre>
|
||||
</td>
|
||||
<td th:if="${booking.reason.isStartBooking}" colspan="4" class="l">
|
||||
Startbuchung
|
||||
</td>
|
||||
<td th:if="${booking.reason.customerOrder != null}" colspan="4" class="l">
|
||||
<a th:href="${'/intern/customerOrders/' + booking.reason.customerOrder.id}">
|
||||
Bestellung: <span th:text="${booking.reason.customerOrder.id}"></span>
|
||||
</a>
|
||||
<pre th:text="${booking.reason.customerOrder.destination.toString()}"></pre>
|
||||
</td>
|
||||
<td th:if="${booking.reason.supplierOrder != null}" colspan="4" class="l">
|
||||
<a th:href="${'/intern/supplierOrders/#q=' + booking.reason.supplierOrder.id}">
|
||||
Lieferung: <span th:text="${booking.reason.supplierOrder.id}"></span>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<!-------------------------------------------------------------->
|
||||
<tr data-group="3">
|
||||
<td>2020-01-12 12:18</td>
|
||||
<td colspan="4" class="l">
|
||||
<a th:href="@{/intern/customerOrders/4808}">Bestellung 8408</a>
|
||||
<div>
|
||||
Hans Maier <br/>
|
||||
Hauptstraße 12<br/>
|
||||
74880 Musterstadt<br/>
|
||||
Deutschland <br/>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<form th:action="@{/intern/warehouse/progress/5410}" method="post">
|
||||
<button type="submit">Beginnen</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<tr data-group="3">
|
||||
<td><img th:src="@{/img/product-1.jpg}" class="s"/></td>
|
||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
||||
<td>1</td>
|
||||
<td><a th:href="@{/intern/warehouse/slots/#q=%231}">Lagerplatz 01</a></td>
|
||||
<td> -</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr data-group="3">
|
||||
<td><img th:src="@{/img/product-2.jpg}" class="s"/></td>
|
||||
<td><a th:href="@{/intern/listedArticles/4205}">Spielzeugauto</a></td>
|
||||
<td>2</td>
|
||||
<td><a th:href="@{/intern/warehouse/slots/#q=%232}">Lagerplatz 02</a></td>
|
||||
<td> -</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
<!-------------------------------------------------------------->
|
||||
<tr data-group="2">
|
||||
<td>2020-01-12 12:15</td>
|
||||
<td colspan="4" class="l">
|
||||
Manuell: Ware war defekt.
|
||||
</td>
|
||||
<td><a class="secondary button">Abschließen</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr data-group="2">
|
||||
<td><img th:src="@{/img/product-1.jpg}" class="s"/></td>
|
||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
||||
<td>1</td>
|
||||
<td><a th:href="@{/intern/warehouse/slots/#q=%231}">Lagerplatz 01</a></td>
|
||||
<td> -</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<td th:if="${!booking.isInProgress}">
|
||||
<form th:action="${'/intern/warehouse/progress/' + booking.id}" method="post">
|
||||
<button type="submit">Beginnen</button>
|
||||
</form>
|
||||
</td>
|
||||
<td th:if="${booking.isInProgress}">
|
||||
<form th:action="${'/intern/warehouse/progress/' + booking.id}" method="get">
|
||||
<button class="secondary" type="submit">Abschließen</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr th:each="pos : ${booking.positions}" th:data-group="${booking.id}">
|
||||
<td><img th:src="@{/shop/articles/{id}/image.jpg(id=${pos.article.id})}" class="s"/></td>
|
||||
<td><a th:href="@{/intern/articles/{id}(id=${pos.article.id})}"
|
||||
th:text="${pos.article.title}"></a></td>
|
||||
<th:block th:if="${pos.amount > 0}">
|
||||
<td th:text="${pos.amount}"></td>
|
||||
<td> -</td>
|
||||
<td><a th:href="${'/intern/warehouse/slots/#q=%23' + pos.slotEntry.slot.slotNum}">Lagerplatz
|
||||
<span th:text="${pos.slotEntry.slot.slotNum}"></span> </a></td>
|
||||
</th:block>
|
||||
<th:block th:if="${pos.amount < 0}">
|
||||
<td th:text="${pos.amount * -1}"></td>
|
||||
<td><a th:href="${'/intern/warehouse/slots/#q=%23' + pos.slotEntry.slot.slotNum}">Lagerplatz
|
||||
<span th:text="${pos.slotEntry.slot.slotNum}"></span> </a></td>
|
||||
<td> -</td>
|
||||
</th:block>
|
||||
<th:block th:if="${pos.amount == 0}">
|
||||
<td th:text="${pos.amount}"></td>
|
||||
<td> -</td>
|
||||
<td> -</td>
|
||||
</th:block>
|
||||
</tr>
|
||||
</th:block>
|
||||
</table>
|
||||
</p>
|
||||
</div>
|
||||
|
|
Reference in New Issue