Digitale bierlijst

cli.py 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. import click
  2. from piket_client.model import (
  3. ServerStatus,
  4. NetworkError,
  5. Consumption,
  6. Person,
  7. Settlement,
  8. ConsumptionType,
  9. )
  10. from prettytable import PrettyTable
  11. @click.group()
  12. def cli():
  13. """Poke coco from the command line."""
  14. pass
  15. @cli.command()
  16. def status():
  17. """Show the current status of the server."""
  18. status = ServerStatus.is_server_running()
  19. if isinstance(status, NetworkError):
  20. print_error(f"Failed to get data from server, error {status.value}")
  21. return
  22. print_ok("Server is available.")
  23. open_consumptions = ServerStatus.unsettled_consumptions()
  24. if isinstance(open_consumptions, NetworkError):
  25. print_error(
  26. f"Failed to get unsettled consumptions, error {open_consumptions.value}"
  27. )
  28. return
  29. click.echo(f"There are {open_consumptions.amount} unsettled consumptions.")
  30. if open_consumptions.amount > 0:
  31. click.echo(f"First at: {open_consumptions.first_timestamp.strftime('%c')}")
  32. click.echo(f"Most recent at: {open_consumptions.last_timestamp.strftime('%c')}")
  33. @cli.group()
  34. def people():
  35. pass
  36. @people.command("list")
  37. @click.option("--active/--inactive", default=None)
  38. def list_people(active: bool) -> None:
  39. people = Person.get_all(active=active)
  40. if isinstance(people, NetworkError):
  41. print_error(f"Could not get people: {people.value}")
  42. return
  43. table = PrettyTable()
  44. table.field_names = ["ID", "Full name", "Display name", "Active"]
  45. table.align["ID"] = "r"
  46. table.align["Full name"] = "l"
  47. table.align["Display name"] = "l"
  48. table.sortby = "Full name"
  49. for p in people:
  50. table.add_row([p.person_id, p.full_name, p.display_name, p.active])
  51. print(table)
  52. @cli.group()
  53. def settlements():
  54. pass
  55. @settlements.command("show")
  56. @click.argument("settlement_id", type=click.INT)
  57. def show_settlement(settlement_id: int) -> None:
  58. """Get and view the contents of a Settlement."""
  59. s = Settlement.get(settlement_id)
  60. if isinstance(s, NetworkError):
  61. print_error(f"Could not get Settlement: {s.value}")
  62. return
  63. output_settlement_info(s)
  64. @settlements.command("create")
  65. @click.argument("name")
  66. def create_settlement(name: str) -> None:
  67. """Create a new Settlement."""
  68. s = Settlement.create(name)
  69. if isinstance(s, NetworkError):
  70. print_error(f"Could not create Settlement: {s.value}")
  71. return
  72. output_settlement_info(s)
  73. def output_settlement_info(s: Settlement) -> None:
  74. click.echo(f'Settlement {s.settlement_id}, "{s.name}"')
  75. click.echo(f"Summary:")
  76. for key, value in s.consumption_summary.items():
  77. click.echo(f" - {value['count']} {value['name']} ({key})")
  78. ct_name_by_id = {key: value["name"] for key, value in s.consumption_summary.items()}
  79. table = PrettyTable()
  80. table.field_names = ["Name", *ct_name_by_id.values()]
  81. table.sortby = "Name"
  82. table.align = "r"
  83. table.align["Name"] = "l" # type: ignore
  84. zero_fields = {k: "" for k in ct_name_by_id.values()}
  85. for item in s.per_person_counts.values():
  86. r = {"Name": item["full_name"], **zero_fields}
  87. for key, value in item["counts"].items():
  88. r[ct_name_by_id[key]] = value
  89. table.add_row(r.values())
  90. print(table)
  91. @cli.group()
  92. def consumption_types():
  93. pass
  94. @consumption_types.command("list")
  95. def list_consumption_types() -> None:
  96. active = ConsumptionType.get_all(active=True)
  97. inactive = ConsumptionType.get_all(active=False)
  98. if isinstance(active, NetworkError) or isinstance(inactive, NetworkError):
  99. print_error("Could not get consumption types!")
  100. return
  101. table = PrettyTable()
  102. table.field_names = ["ID", "Name", "Active"]
  103. table.sortby = "ID"
  104. for ct in active + inactive:
  105. table.add_row([ct.consumption_type_id, ct.name, ct.active])
  106. print(table)
  107. @consumption_types.command("create")
  108. @click.argument("name")
  109. def create_consumption_type(name: str) -> None:
  110. ct = ConsumptionType(name=name).create()
  111. if not isinstance(ct, NetworkError):
  112. print_ok(f'Created consumption type "{name}" with ID {ct.consumption_type_id}.')
  113. @consumption_types.command("activate")
  114. @click.argument("consumption_type_id", type=click.INT)
  115. def activate_consumption_type(consumption_type_id: int) -> None:
  116. ct = ConsumptionType.get(consumption_type_id)
  117. if isinstance(ct, NetworkError):
  118. print_error(f"Could not get ConsumptionType: {ct.value}")
  119. return
  120. result = ct.set_active(True)
  121. if not isinstance(result, NetworkError):
  122. print_ok(
  123. f"Consumption type {ct.consumption_type_id} ({ct.name}) is now active."
  124. )
  125. @consumption_types.command("deactivate")
  126. @click.argument("consumption_type_id", type=click.INT)
  127. def deactivate_consumption_type(consumption_type_id: int) -> None:
  128. ct = ConsumptionType.get(consumption_type_id)
  129. if isinstance(ct, NetworkError):
  130. print_error(f"Could not get ConsumptionType: {ct.value}")
  131. return
  132. result = ct.set_active(False)
  133. if not isinstance(result, NetworkError):
  134. print_ok(
  135. f"Consumption type {ct.consumption_type_id} ({ct.name}) is now inactive."
  136. )
  137. def print_ok(msg: str) -> None:
  138. click.echo(click.style(msg, fg="green"))
  139. def print_error(msg: str) -> None:
  140. click.echo(click.style(msg, fg="red", bold=True), err=True)
  141. if __name__ == "__main__":
  142. cli()