image.png
    新增HeadOfficeView页面:

    1. <html>
    2. <body>
    3. <div>
    4. Balance : $<span id="balance"></span>
    5. </div>
    6. <div>
    7. Cash : $<span id="cash"></span>
    8. </div>
    9. </br>
    10. <table style="width: 100%" border="1">
    11. <tr>
    12. <th>Snack machines</th>
    13. <th>ATMs</th>
    14. </tr>
    15. <tr>
    16. <td>
    17. 212
    18. <table style="width: 100%">
    19. <tr>
    20. <td>
    21. <ul id="snackMachineList" type="none">
    22. <li>
    23. <span>Id</span>&nbsp&nbsp<span>Money</span></li>
    24. </ul>
    25. </td>
    26. </tr>
    27. </table>
    28. </td>
    29. <td>
    30. <table style="width: 100%">
    31. <tr>
    32. <td>
    33. <ul id="atmList" type="none">
    34. <li>
    35. <span>Id</span>&nbsp&nbsp<span>Cash</span></li>
    36. </ul>
    37. </td>
    38. </tr>
    39. <!-- <tr>
    40. <td>Id</td>
    41. <td>Cash</td>
    42. </tr>
    43. <tr>
    44. <td id="atmId">1</td>
    45. <td id="cash">$4</td>
    46. <td><a href="../atm/AtmView.html">Show</a></td>
    47. <td><button id="btnLoad">
    48. Load cash
    49. </buton></td>
    50. </tr> -->
    51. </table>
    52. </td>
    53. </tr>
    54. </table>
    55. </br>
    56. </br>
    57. </br>
    58. <div>Move cash from Snack machine to Head office :</div>
    59. <input type="text" id="snackmachineId" placeholder="Enter SnackMachine Id"/>
    60. <button id="btnUnload">Unload</button>
    61. </br>
    62. </br>
    63. </br>
    64. <div>Move cash from Head office to Atm :</div>
    65. <input type="text" id="atmId" placeholder="Enter Atm Id"/>
    66. <button id="btnLoad">Load</button>
    67. <script src="../common/jquery-3.6.0.min.js"></script>
    68. <script src="headOffice.js"></script>
    69. </body>
    70. </html>

    页面展示系统的SnackMachine和ATM数量,HeadOffice的手续费和余额。点击SnackMachine的ID字段展示详情,假设SnackMachine的余额是0,当购买3元的巧克力后,余额是3.此时可以将这3元转移到HeadOffice中,随后SnackMachine的余额变为0.我们还可以将HeadOffice的钱从ATM取出,取出3元续收手续费0.03元。我们继续完善其它类:

    1. package com.lugew.domaindrivendesignwithspringboot.management;
    2. import com.lugew.domaindrivendesignwithspringboot.atm.Atm;
    3. import com.lugew.domaindrivendesignwithspringboot.common.AggregateRoot;
    4. import com.lugew.domaindrivendesignwithspringboot.sharedkernel.Money;
    5. import com.lugew.domaindrivendesignwithspringboot.snackmachine.SnackMachine;
    6. import lombok.Getter;
    7. import lombok.Setter;
    8. import static com.lugew.domaindrivendesignwithspringboot.sharedkernel.Money.None;
    9. @Getter
    10. @Setter
    11. public class HeadOffice extends AggregateRoot {
    12. private float balance;
    13. private Money cash = None;
    14. public void unloadCashFromSnackMachine(SnackMachine snackMachine) {
    15. Money money = snackMachine.unloadMoney();
    16. cash = cash.add(money);
    17. }
    18. public void loadCashToAtm(Atm atm) {
    19. atm.loadMoney(cash);
    20. cash = Money.None;
    21. }
    22. public void changeBalance(float delta) {
    23. balance += delta;
    24. }
    25. public HeadOfficeDto convertToHeadOfficeDto() {
    26. HeadOfficeDto headOfficeDto = new HeadOfficeDto();
    27. headOfficeDto.setId(id);
    28. headOfficeDto.setBalance(balance);
    29. headOfficeDto.setOneCentCount(cash.getOneCentCount());
    30. headOfficeDto.setTenCentCount(cash.getTenCentCount());
    31. headOfficeDto.setQuarterCount(cash.getQuarterCount());
    32. headOfficeDto.setOneDollarCount(cash.getOneDollarCount());
    33. headOfficeDto.setFiveDollarCount(cash.getFiveDollarCount());
    34. headOfficeDto.setTwentyDollarCount(cash.getTwentyDollarCount());
    35. return headOfficeDto;
    36. }
    37. }
    1. package com.lugew.domaindrivendesignwithspringboot.snackmachine;
    2. import com.lugew.domaindrivendesignwithspringboot.common.AggregateRoot;
    3. import com.lugew.domaindrivendesignwithspringboot.sharedkernel.Money;
    4. import lombok.Getter;
    5. import lombok.Setter;
    6. import java.util.ArrayList;
    7. import java.util.Arrays;
    8. import java.util.List;
    9. import static com.lugew.domaindrivendesignwithspringboot.sharedkernel.Money.None;
    10. public final class SnackMachine extends AggregateRoot {
    11. @Getter
    12. @Setter
    13. private Money moneyInside;
    14. @Getter
    15. @Setter
    16. private float moneyInTransaction;
    17. @Setter
    18. private List<Slot> slots;
    19. public SnackMachine() {
    20. moneyInside = None;
    21. moneyInTransaction = 0;
    22. slots = new ArrayList<>();
    23. slots.add(new Slot(this, 1));
    24. slots.add(new Slot(this, 2));
    25. slots.add(new Slot(this, 3));
    26. }
    27. public Money unloadMoney() {
    28. if (moneyInTransaction > 0)
    29. throw new IllegalStateException();
    30. Money money = moneyInside;
    31. moneyInside = Money.None;
    32. return money;
    33. }
    34. public Slot getSlot(int position) {
    35. return slots.stream().filter(x -> x.getPosition() ==
    36. position).findAny().orElse(null);
    37. }
    38. public SnackPile getSnackPile(int position) {
    39. return getSlot(position).getSnackPile();
    40. }
    41. public void insertMoney(Money money) {
    42. Money[] coinsAndNotes = {Money.Cent, Money.TenCent, Money.Quarter,
    43. Money.Dollar, Money.FiveDollar,
    44. Money.TwentyDollar};
    45. if (!Arrays.asList(coinsAndNotes).contains(money))
    46. throw new IllegalStateException();
    47. moneyInTransaction = moneyInTransaction + money.getAmount();
    48. moneyInside = moneyInside.add(money);
    49. }
    50. public void returnMoney() {
    51. Money moneyToReturn = moneyInside.allocate(moneyInTransaction);
    52. moneyInside = moneyInside.substract(moneyToReturn);
    53. moneyInTransaction = 0;
    54. }
    55. public void buySnack(int position) {
    56. Slot slot = getSlot(position);
    57. if (slot.getSnackPile().getPrice() > moneyInTransaction) {
    58. throw new IllegalStateException();
    59. }
    60. slot.setSnackPile(slot.getSnackPile().subtractOne());
    61. Money change = moneyInside.allocate(moneyInTransaction - slot.getSnackPile().getPrice());
    62. if (change.getAmount() < moneyInTransaction - slot.getSnackPile().getPrice()) {
    63. throw new IllegalStateException();
    64. }
    65. moneyInside = moneyInside.substract(change);
    66. moneyInTransaction = 0;
    67. }
    68. public SnackMachineDto convertToSnackMachineDto() {
    69. SnackMachineDto snackMachineDto = new SnackMachineDto();
    70. snackMachineDto.setId(id);
    71. snackMachineDto.setMoneyInTransaction(moneyInTransaction);
    72. List<SlotDto> slotDtoList = new ArrayList<>();
    73. for (Slot slot : slots) slotDtoList.add(slot.convertToSlotDto());
    74. snackMachineDto.setSlotDtoList(slotDtoList);
    75. snackMachineDto.setOneCentCount(moneyInside.getOneCentCount());
    76. snackMachineDto.setTenCentCount(moneyInside.getTenCentCount());
    77. snackMachineDto.setQuarterCount(moneyInside.getQuarterCount());
    78. snackMachineDto.setOneDollarCount(moneyInside.getOneDollarCount());
    79. snackMachineDto.setFiveDollarCount(moneyInside.getFiveDollarCount());
    80. snackMachineDto.setTwentyDollarCount(moneyInside.getTwentyDollarCount());
    81. return snackMachineDto;
    82. }
    83. public void loadSnacks(int position, SnackPile snackPile) {
    84. Slot slot = slots.stream().filter(x -> x.getPosition() ==
    85. position).findAny().orElse(null);
    86. if (slot != null) {
    87. slot.setSnackPile(snackPile);
    88. }
    89. }
    90. public void loadMoney(Money money) {
    91. moneyInside = moneyInside.add(money);
    92. }
    93. }
    1. package com.lugew.domaindrivendesignwithspringboot.management;
    2. import com.lugew.domaindrivendesignwithspringboot.atm.Atm;
    3. import com.lugew.domaindrivendesignwithspringboot.atm.AtmDto;
    4. import com.lugew.domaindrivendesignwithspringboot.atm.AtmRepository;
    5. import com.lugew.domaindrivendesignwithspringboot.snackmachine.SnackMachine;
    6. import com.lugew.domaindrivendesignwithspringboot.snackmachine.SnackMachineDto;
    7. import com.lugew.domaindrivendesignwithspringboot.snackmachine.SnackMachineRepository;
    8. import org.springframework.beans.factory.annotation.Autowired;
    9. import org.springframework.http.HttpStatus;
    10. import org.springframework.stereotype.Controller;
    11. import org.springframework.web.bind.annotation.*;
    12. @Controller
    13. @RequestMapping(path = "/headOffice")
    14. public class HeadOfficeController {
    15. @Autowired
    16. private SnackMachineRepository snackMachineRepository;
    17. @Autowired
    18. private AtmRepository atmRepository;
    19. @Autowired
    20. private HeadOfficeRepository headOfficeRepository;
    21. @Autowired
    22. private HeadOfficeInstance headOfficeInstance;
    23. @GetMapping
    24. @ResponseBody
    25. public HeadOfficeDto getHeadOffice() {
    26. return headOfficeInstance.getInstance();
    27. }
    28. @PutMapping("/{atmId}/loadCash")
    29. @ResponseStatus(HttpStatus.OK)
    30. public void loadCashToAtm(@PathVariable("atmId") long atmId) {
    31. AtmDto atmDto = atmRepository.findById(atmId).orElse(null);
    32. HeadOfficeDto headOfficeDto = headOfficeInstance.getInstance();
    33. Atm atm = atmDto.convertToAtm();
    34. HeadOffice headOffice = headOfficeDto.convertToHeadOffice();
    35. headOffice.loadCashToAtm(atm);
    36. atmRepository.save(atm.convertToAtmDto());
    37. headOfficeRepository.save(headOffice.convertToHeadOfficeDto());
    38. }
    39. @PutMapping("/{snackMachineId}/unloadCash")
    40. @ResponseStatus(HttpStatus.OK)
    41. public void unloadCash(@PathVariable("snackMachineId") long snackMachineId) {
    42. SnackMachineDto snackMachineDto =
    43. snackMachineRepository.findById(snackMachineId).orElse(null);
    44. if (snackMachineDto == null) return;
    45. HeadOfficeDto headOfficeDto = headOfficeInstance.getInstance();
    46. HeadOffice headOffice = headOfficeDto.convertToHeadOffice();
    47. SnackMachine snackMachine = snackMachineDto.convertToSnackMachine();
    48. headOffice.unloadCashFromSnackMachine(snackMachine);
    49. snackMachineRepository.save(snackMachine.convertToSnackMachineDto());
    50. headOfficeRepository.save(headOffice.convertToHeadOfficeDto());
    51. }
    52. }
    1. const headOfficeUri = "http://localhost:23333/headOffice";
    2. getHeadOffice();
    3. function getHeadOffice() {
    4. $.get(headOfficeUri, function (data, status) {
    5. $('#cash').html(data.amount);
    6. $('#balance').html(data.balance);
    7. });
    8. }
    9. const snackMachineUri = "http://localhost:23333/snackmachines";
    10. getSnackMachines();
    11. function getSnackMachines() {
    12. $.get(snackMachineUri, function (data, status) {
    13. var list = data == null ? [] : (data instanceof Array ? data : [data]);
    14. $.each(list, function (index, item) {
    15. $('#snackMachineList').append(
    16. '<li><a href="../snackMachine/SnackMachineView.html?id=' + item.id + '">' + item.id + '</a>&nbsp&nbsp&nbsp&nbsp<span>$' + item.amount + '</span></li>');
    17. });
    18. });
    19. }
    20. const atmUri = "http://localhost:23333/atms";
    21. getAtms();
    22. function getAtms() {
    23. $.get(atmUri, function (data, status) {
    24. var list = data == null ? [] : (data instanceof Array ? data : [data]);
    25. $.each(list, function (index, item) {
    26. $('#atmList').append(
    27. '<li><a href="../atm/AtmView.html?id=' + item.id + '">' + item.id + '</a>&nbsp&nbsp&nbsp&nbsp<span>$' + item.amount + '</span> </li>');
    28. });
    29. });
    30. }
    31. $("#btnUnload").click(function () {
    32. var snackmachineId = $('#snackmachineId').val();
    33. $.ajax({
    34. url: headOfficeUri + '/' + snackmachineId + '/unloadCash',
    35. type: 'PUT',
    36. success: function (data) {
    37. }
    38. });
    39. });
    40. $("#btnLoad").click(function () {
    41. var atmId = $('#atmId').val();
    42. $.ajax({
    43. url: headOfficeUri + '/' + atmId + '/loadCash',
    44. type: 'PUT',
    45. success: function (data) {
    46. }
    47. });
    48. });

    来看看目前的代码结构:
    image.png
    image.png
    同时准备初始化sql:

    1. insert into snack_dto (name, id)
    2. values ('Chocolate', 1);
    3. insert into snack_dto (name, id)
    4. values ('Soda', 2);
    5. insert into snack_dto (name, id)
    6. values ('Gum', 3);
    7. insert into snack_machine_dto (five_dollar_count, money_in_transaction,
    8. one_cent_count, one_dollar_count,
    9. quarter_count, ten_cent_count, twenty_dollar_count, id)
    10. values (100, 0.0, 100, 100, 100,
    11. 100, 100, 1);
    12. insert into slot_dto (position, price, quantity, snack_dto_id, id)
    13. values (1, 40.0, 100, 1, 2);
    14. insert into slot_dto (position, price, quantity, snack_dto_id, id)
    15. values (2, 20.0, 100, 2, 3);
    16. insert into slot_dto (position, price, quantity, snack_dto_id, id)
    17. values (3, 10.0, 100, 3, 4);
    18. update slot_dto
    19. set snack_machine_id=1
    20. where id = 2;
    21. update slot_dto
    22. set snack_machine_id=1
    23. where id = 3;
    24. update slot_dto
    25. set snack_machine_id=1
    26. where id = 4;
    27. insert into snack_machine_dto (five_dollar_count, money_in_transaction,
    28. one_cent_count, one_dollar_count,
    29. quarter_count, ten_cent_count, twenty_dollar_count, id)
    30. values (10, 0.0, 10, 10, 10, 10,
    31. 10, 2);
    32. insert into slot_dto (position, price, quantity, snack_dto_id, id)
    33. values (1, 40.0, 100, 1, 5);
    34. insert into slot_dto (position, price, quantity, snack_dto_id, id)
    35. values (2, 20.0, 100, 2, 6);
    36. insert into slot_dto (position, price, quantity, snack_dto_id, id)
    37. values (3, 10.0, 100, 3, 7);
    38. update slot_dto
    39. set snack_machine_id=2
    40. where id = 5;
    41. update slot_dto
    42. set snack_machine_id=2
    43. where id = 6;
    44. update slot_dto
    45. set snack_machine_id=2
    46. where id = 7;
    47. insert into ATM_DTO (money_charged, one_cent_count, one_dollar_count,
    48. quarter_count, ten_cent_count, five_dollar_count, twenty_dollar_count, id)
    49. values (0, 50,
    50. 50, 50, 50, 50, 50, 1);
    51. insert into ATM_DTO (money_charged, one_cent_count, one_dollar_count,
    52. quarter_count, ten_cent_count, five_dollar_count, twenty_dollar_count, id)
    53. values (0, 20,
    54. 20, 20, 20, 20, 20, 2);
    55. insert into HEAD_OFFICE_DTO (balance, one_cent_count, one_dollar_count,
    56. quarter_count, ten_cent_count, five_dollar_count, twenty_dollar_count, id)
    57. values (0, 0,
    58. 0, 0, 0, 0, 0, 1);

    运行项目:
    image.png
    image.png