新增HeadOfficeView页面:
<html>
<body>
<div>
Balance : $<span id="balance"></span>
</div>
<div>
Cash : $<span id="cash"></span>
</div>
</br>
<table style="width: 100%" border="1">
<tr>
<th>Snack machines</th>
<th>ATMs</th>
</tr>
<tr>
<td>
212
<table style="width: 100%">
<tr>
<td>
<ul id="snackMachineList" type="none">
<li>
<span>Id</span>  <span>Money</span></li>
</ul>
</td>
</tr>
</table>
</td>
<td>
<table style="width: 100%">
<tr>
<td>
<ul id="atmList" type="none">
<li>
<span>Id</span>  <span>Cash</span></li>
</ul>
</td>
</tr>
<!-- <tr>
<td>Id</td>
<td>Cash</td>
</tr>
<tr>
<td id="atmId">1</td>
<td id="cash">$4</td>
<td><a href="../atm/AtmView.html">Show</a></td>
<td><button id="btnLoad">
Load cash
</buton></td>
</tr> -->
</table>
</td>
</tr>
</table>
</br>
</br>
</br>
<div>Move cash from Snack machine to Head office :</div>
<input type="text" id="snackmachineId" placeholder="Enter SnackMachine Id"/>
<button id="btnUnload">Unload</button>
</br>
</br>
</br>
<div>Move cash from Head office to Atm :</div>
<input type="text" id="atmId" placeholder="Enter Atm Id"/>
<button id="btnLoad">Load</button>
<script src="../common/jquery-3.6.0.min.js"></script>
<script src="headOffice.js"></script>
</body>
</html>
页面展示系统的SnackMachine和ATM数量,HeadOffice的手续费和余额。点击SnackMachine的ID字段展示详情,假设SnackMachine的余额是0,当购买3元的巧克力后,余额是3.此时可以将这3元转移到HeadOffice中,随后SnackMachine的余额变为0.我们还可以将HeadOffice的钱从ATM取出,取出3元续收手续费0.03元。我们继续完善其它类:
package com.lugew.domaindrivendesignwithspringboot.management;
import com.lugew.domaindrivendesignwithspringboot.atm.Atm;
import com.lugew.domaindrivendesignwithspringboot.common.AggregateRoot;
import com.lugew.domaindrivendesignwithspringboot.sharedkernel.Money;
import com.lugew.domaindrivendesignwithspringboot.snackmachine.SnackMachine;
import lombok.Getter;
import lombok.Setter;
import static com.lugew.domaindrivendesignwithspringboot.sharedkernel.Money.None;
@Getter
@Setter
public class HeadOffice extends AggregateRoot {
private float balance;
private Money cash = None;
public void unloadCashFromSnackMachine(SnackMachine snackMachine) {
Money money = snackMachine.unloadMoney();
cash = cash.add(money);
}
public void loadCashToAtm(Atm atm) {
atm.loadMoney(cash);
cash = Money.None;
}
public void changeBalance(float delta) {
balance += delta;
}
public HeadOfficeDto convertToHeadOfficeDto() {
HeadOfficeDto headOfficeDto = new HeadOfficeDto();
headOfficeDto.setId(id);
headOfficeDto.setBalance(balance);
headOfficeDto.setOneCentCount(cash.getOneCentCount());
headOfficeDto.setTenCentCount(cash.getTenCentCount());
headOfficeDto.setQuarterCount(cash.getQuarterCount());
headOfficeDto.setOneDollarCount(cash.getOneDollarCount());
headOfficeDto.setFiveDollarCount(cash.getFiveDollarCount());
headOfficeDto.setTwentyDollarCount(cash.getTwentyDollarCount());
return headOfficeDto;
}
}
package com.lugew.domaindrivendesignwithspringboot.snackmachine;
import com.lugew.domaindrivendesignwithspringboot.common.AggregateRoot;
import com.lugew.domaindrivendesignwithspringboot.sharedkernel.Money;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.lugew.domaindrivendesignwithspringboot.sharedkernel.Money.None;
public final class SnackMachine extends AggregateRoot {
@Getter
@Setter
private Money moneyInside;
@Getter
@Setter
private float moneyInTransaction;
@Setter
private List<Slot> slots;
public SnackMachine() {
moneyInside = None;
moneyInTransaction = 0;
slots = new ArrayList<>();
slots.add(new Slot(this, 1));
slots.add(new Slot(this, 2));
slots.add(new Slot(this, 3));
}
public Money unloadMoney() {
if (moneyInTransaction > 0)
throw new IllegalStateException();
Money money = moneyInside;
moneyInside = Money.None;
return money;
}
public Slot getSlot(int position) {
return slots.stream().filter(x -> x.getPosition() ==
position).findAny().orElse(null);
}
public SnackPile getSnackPile(int position) {
return getSlot(position).getSnackPile();
}
public void insertMoney(Money money) {
Money[] coinsAndNotes = {Money.Cent, Money.TenCent, Money.Quarter,
Money.Dollar, Money.FiveDollar,
Money.TwentyDollar};
if (!Arrays.asList(coinsAndNotes).contains(money))
throw new IllegalStateException();
moneyInTransaction = moneyInTransaction + money.getAmount();
moneyInside = moneyInside.add(money);
}
public void returnMoney() {
Money moneyToReturn = moneyInside.allocate(moneyInTransaction);
moneyInside = moneyInside.substract(moneyToReturn);
moneyInTransaction = 0;
}
public void buySnack(int position) {
Slot slot = getSlot(position);
if (slot.getSnackPile().getPrice() > moneyInTransaction) {
throw new IllegalStateException();
}
slot.setSnackPile(slot.getSnackPile().subtractOne());
Money change = moneyInside.allocate(moneyInTransaction - slot.getSnackPile().getPrice());
if (change.getAmount() < moneyInTransaction - slot.getSnackPile().getPrice()) {
throw new IllegalStateException();
}
moneyInside = moneyInside.substract(change);
moneyInTransaction = 0;
}
public SnackMachineDto convertToSnackMachineDto() {
SnackMachineDto snackMachineDto = new SnackMachineDto();
snackMachineDto.setId(id);
snackMachineDto.setMoneyInTransaction(moneyInTransaction);
List<SlotDto> slotDtoList = new ArrayList<>();
for (Slot slot : slots) slotDtoList.add(slot.convertToSlotDto());
snackMachineDto.setSlotDtoList(slotDtoList);
snackMachineDto.setOneCentCount(moneyInside.getOneCentCount());
snackMachineDto.setTenCentCount(moneyInside.getTenCentCount());
snackMachineDto.setQuarterCount(moneyInside.getQuarterCount());
snackMachineDto.setOneDollarCount(moneyInside.getOneDollarCount());
snackMachineDto.setFiveDollarCount(moneyInside.getFiveDollarCount());
snackMachineDto.setTwentyDollarCount(moneyInside.getTwentyDollarCount());
return snackMachineDto;
}
public void loadSnacks(int position, SnackPile snackPile) {
Slot slot = slots.stream().filter(x -> x.getPosition() ==
position).findAny().orElse(null);
if (slot != null) {
slot.setSnackPile(snackPile);
}
}
public void loadMoney(Money money) {
moneyInside = moneyInside.add(money);
}
}
package com.lugew.domaindrivendesignwithspringboot.management;
import com.lugew.domaindrivendesignwithspringboot.atm.Atm;
import com.lugew.domaindrivendesignwithspringboot.atm.AtmDto;
import com.lugew.domaindrivendesignwithspringboot.atm.AtmRepository;
import com.lugew.domaindrivendesignwithspringboot.snackmachine.SnackMachine;
import com.lugew.domaindrivendesignwithspringboot.snackmachine.SnackMachineDto;
import com.lugew.domaindrivendesignwithspringboot.snackmachine.SnackMachineRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping(path = "/headOffice")
public class HeadOfficeController {
@Autowired
private SnackMachineRepository snackMachineRepository;
@Autowired
private AtmRepository atmRepository;
@Autowired
private HeadOfficeRepository headOfficeRepository;
@Autowired
private HeadOfficeInstance headOfficeInstance;
@GetMapping
@ResponseBody
public HeadOfficeDto getHeadOffice() {
return headOfficeInstance.getInstance();
}
@PutMapping("/{atmId}/loadCash")
@ResponseStatus(HttpStatus.OK)
public void loadCashToAtm(@PathVariable("atmId") long atmId) {
AtmDto atmDto = atmRepository.findById(atmId).orElse(null);
HeadOfficeDto headOfficeDto = headOfficeInstance.getInstance();
Atm atm = atmDto.convertToAtm();
HeadOffice headOffice = headOfficeDto.convertToHeadOffice();
headOffice.loadCashToAtm(atm);
atmRepository.save(atm.convertToAtmDto());
headOfficeRepository.save(headOffice.convertToHeadOfficeDto());
}
@PutMapping("/{snackMachineId}/unloadCash")
@ResponseStatus(HttpStatus.OK)
public void unloadCash(@PathVariable("snackMachineId") long snackMachineId) {
SnackMachineDto snackMachineDto =
snackMachineRepository.findById(snackMachineId).orElse(null);
if (snackMachineDto == null) return;
HeadOfficeDto headOfficeDto = headOfficeInstance.getInstance();
HeadOffice headOffice = headOfficeDto.convertToHeadOffice();
SnackMachine snackMachine = snackMachineDto.convertToSnackMachine();
headOffice.unloadCashFromSnackMachine(snackMachine);
snackMachineRepository.save(snackMachine.convertToSnackMachineDto());
headOfficeRepository.save(headOffice.convertToHeadOfficeDto());
}
}
const headOfficeUri = "http://localhost:23333/headOffice";
getHeadOffice();
function getHeadOffice() {
$.get(headOfficeUri, function (data, status) {
$('#cash').html(data.amount);
$('#balance').html(data.balance);
});
}
const snackMachineUri = "http://localhost:23333/snackmachines";
getSnackMachines();
function getSnackMachines() {
$.get(snackMachineUri, function (data, status) {
var list = data == null ? [] : (data instanceof Array ? data : [data]);
$.each(list, function (index, item) {
$('#snackMachineList').append(
'<li><a href="../snackMachine/SnackMachineView.html?id=' + item.id + '">' + item.id + '</a>    <span>$' + item.amount + '</span></li>');
});
});
}
const atmUri = "http://localhost:23333/atms";
getAtms();
function getAtms() {
$.get(atmUri, function (data, status) {
var list = data == null ? [] : (data instanceof Array ? data : [data]);
$.each(list, function (index, item) {
$('#atmList').append(
'<li><a href="../atm/AtmView.html?id=' + item.id + '">' + item.id + '</a>    <span>$' + item.amount + '</span> </li>');
});
});
}
$("#btnUnload").click(function () {
var snackmachineId = $('#snackmachineId').val();
$.ajax({
url: headOfficeUri + '/' + snackmachineId + '/unloadCash',
type: 'PUT',
success: function (data) {
}
});
});
$("#btnLoad").click(function () {
var atmId = $('#atmId').val();
$.ajax({
url: headOfficeUri + '/' + atmId + '/loadCash',
type: 'PUT',
success: function (data) {
}
});
});
来看看目前的代码结构:
同时准备初始化sql:
insert into snack_dto (name, id)
values ('Chocolate', 1);
insert into snack_dto (name, id)
values ('Soda', 2);
insert into snack_dto (name, id)
values ('Gum', 3);
insert into snack_machine_dto (five_dollar_count, money_in_transaction,
one_cent_count, one_dollar_count,
quarter_count, ten_cent_count, twenty_dollar_count, id)
values (100, 0.0, 100, 100, 100,
100, 100, 1);
insert into slot_dto (position, price, quantity, snack_dto_id, id)
values (1, 40.0, 100, 1, 2);
insert into slot_dto (position, price, quantity, snack_dto_id, id)
values (2, 20.0, 100, 2, 3);
insert into slot_dto (position, price, quantity, snack_dto_id, id)
values (3, 10.0, 100, 3, 4);
update slot_dto
set snack_machine_id=1
where id = 2;
update slot_dto
set snack_machine_id=1
where id = 3;
update slot_dto
set snack_machine_id=1
where id = 4;
insert into snack_machine_dto (five_dollar_count, money_in_transaction,
one_cent_count, one_dollar_count,
quarter_count, ten_cent_count, twenty_dollar_count, id)
values (10, 0.0, 10, 10, 10, 10,
10, 2);
insert into slot_dto (position, price, quantity, snack_dto_id, id)
values (1, 40.0, 100, 1, 5);
insert into slot_dto (position, price, quantity, snack_dto_id, id)
values (2, 20.0, 100, 2, 6);
insert into slot_dto (position, price, quantity, snack_dto_id, id)
values (3, 10.0, 100, 3, 7);
update slot_dto
set snack_machine_id=2
where id = 5;
update slot_dto
set snack_machine_id=2
where id = 6;
update slot_dto
set snack_machine_id=2
where id = 7;
insert into ATM_DTO (money_charged, one_cent_count, one_dollar_count,
quarter_count, ten_cent_count, five_dollar_count, twenty_dollar_count, id)
values (0, 50,
50, 50, 50, 50, 50, 1);
insert into ATM_DTO (money_charged, one_cent_count, one_dollar_count,
quarter_count, ten_cent_count, five_dollar_count, twenty_dollar_count, id)
values (0, 20,
20, 20, 20, 20, 20, 2);
insert into HEAD_OFFICE_DTO (balance, one_cent_count, one_dollar_count,
quarter_count, ten_cent_count, five_dollar_count, twenty_dollar_count, id)
values (0, 0,
0, 0, 0, 0, 0, 1);
运行项目: