You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

300 line
8.9KB

  1. import {
  2. Box,
  3. Button,
  4. Divider,
  5. Grid,
  6. Paper,
  7. Stack,
  8. Typography,
  9. } from "@mui/material";
  10. import {
  11. ReceiptIssuingOrderHTCustom,
  12. getReceiptIssuingOrders,
  13. } from "api/custom/hello-techno/receipt-issuing-order";
  14. import { PageID } from "codes/page";
  15. import { getPrefName } from "codes/prefcode";
  16. import { SimpleDataList } from "components/table";
  17. import useAPICall from "hooks/useAPICall";
  18. import useBackDrop from "hooks/useBackDrop";
  19. import useDashboard from "hooks/useDashBoard";
  20. import useNavigateCustom from "hooks/useNavigateCustom";
  21. import useSnackbarCustom from "hooks/useSnackbarCustom";
  22. import { isNumber } from "lodash";
  23. import { useEffect, useMemo, useState } from "react";
  24. import { useParams } from "react-router-dom";
  25. import { sprintf } from "sprintf-js";
  26. import { formatDateStr, formatDateTimeStr } from "utils/datetime";
  27. import useMailPostCompleteDialog from "./hooks/useMailPostCompleteDialog";
  28. import { getFullUrl } from "api/url";
  29. import { ApiId } from "api";
  30. import useChangeHandlerDialog from "../../hooks/useChangeHandlerDialog";
  31. export default function ReceiptIssuingOrderDetail() {
  32. const { setHeaderTitle, setTabs } = useDashboard(
  33. PageID.DASHBOARD_RECEIPT_ISSUING_ORDER_DETAIL_CUSTOM_HELLO_TECHNO
  34. );
  35. const { navigate } = useNavigateCustom();
  36. const { error } = useSnackbarCustom();
  37. const { id: receiptIssuingOrderId } = useParams();
  38. const { setShowBackDrop } = useBackDrop();
  39. const [order, setOrder] = useState<ReceiptIssuingOrderHTCustom | null>(null);
  40. const postCompleteDialog = useMailPostCompleteDialog(order, () => {
  41. fetch();
  42. });
  43. const changeHandlerDialog = useChangeHandlerDialog(order, () => {
  44. fetch();
  45. });
  46. const { callAPI, sending } = useAPICall({
  47. apiMethod: getReceiptIssuingOrders,
  48. onSuccess: (res) => {
  49. const target = res.data.records[0];
  50. if (target) {
  51. setOrder(target);
  52. }
  53. },
  54. onFailed: () => {
  55. error("情報取得失敗");
  56. navigate(-1);
  57. },
  58. });
  59. const fetch = () => {
  60. if (receiptIssuingOrderId) {
  61. callAPI({
  62. id: receiptIssuingOrderId,
  63. });
  64. }
  65. };
  66. const hasMailOrder = useMemo(() => {
  67. return !!order?.status_order_mail_datetime;
  68. }, [order]);
  69. const orderInfo = useMemo(() => {
  70. if (!order) return [];
  71. return [
  72. { title: "ステータス", value: order.status_name },
  73. {
  74. title: "担当者",
  75. value: order.handler_name,
  76. end: (
  77. <Button
  78. sx={{ minWidth: 80 }}
  79. onClick={() => {
  80. changeHandlerDialog.open();
  81. }}
  82. >
  83. 担当変更
  84. </Button>
  85. ),
  86. },
  87. { title: "SMS送信先", value: order.sms_phone_number },
  88. { title: "依頼日", value: formatDateStr(order.order_datetime) },
  89. { title: "運営会社", value: order.customer_name },
  90. { title: "駐車場", value: order.parking_name },
  91. { title: "利用日", value: formatDateStr(order.receipt_use_date) },
  92. {
  93. title: "精算連番",
  94. value: isNumber(order.adjust_seq_no)
  95. ? sprintf("%06d", order.adjust_seq_no)
  96. : "-",
  97. },
  98. {
  99. title: "金額",
  100. value: isNumber(order.receipt_amount)
  101. ? order.receipt_amount.toLocaleString() + "円"
  102. : "-",
  103. },
  104. {
  105. title: "消費税(内税)",
  106. value:
  107. isNumber(order.tax_amount) && isNumber(order.tax_rate)
  108. ? order.tax_amount.toLocaleString() + "円(" + order.tax_rate + "%)"
  109. : "-",
  110. },
  111. { title: "備考", value: order.memo },
  112. ];
  113. }, [order]);
  114. const mailStatus1 = useMemo(() => {
  115. if (!order) return [];
  116. return [{ title: "郵送依頼", value: hasMailOrder ? "あり" : "なし" }];
  117. }, [order]);
  118. const mailStatus2 = useMemo(() => {
  119. if (!order || !hasMailOrder) return [];
  120. return [
  121. { title: "郵便番号", value: "〒" + order.mail_zip_code },
  122. { title: "都道府県", value: getPrefName(order.mail_pref_code ?? "") },
  123. { title: "市区町村", value: order.mail_address1 },
  124. { title: "番地等", value: order.mail_address2 },
  125. { title: "建物名/部屋番号等", value: order.mail_address3 },
  126. { title: "宛名", value: order.mail_name },
  127. ];
  128. }, [order]);
  129. const receiptInfo = useMemo(() => {
  130. if (!order) return [];
  131. return [
  132. { title: "領収証番号", value: order.receipt_no },
  133. {
  134. title: "宛名",
  135. value: order.receipt_name,
  136. },
  137. ];
  138. }, [order]);
  139. const actionDatetimes = useMemo(() => {
  140. if (!order) return [];
  141. return [
  142. {
  143. title: "SMS送信",
  144. value: formatDateTimeStr(order.status_sms_send_datetime),
  145. },
  146. {
  147. title: "初回アクセス",
  148. value: formatDateTimeStr(order.status_first_access_datetime),
  149. },
  150. {
  151. title: "領収証確定",
  152. value: formatDateTimeStr(order.status_receipt_confirm_datetime),
  153. },
  154. {
  155. title: "郵送依頼",
  156. value: formatDateTimeStr(order.status_order_mail_datetime),
  157. },
  158. { title: "郵送投函", value: formatDateStr(order.status_mail_post_date) },
  159. {
  160. title: "領収証ダウンロード",
  161. value: formatDateTimeStr(order.status_receipt_download_datetime),
  162. },
  163. {
  164. title: "メール配信依頼",
  165. value: formatDateTimeStr(
  166. order.status_receipt_email_send_order_datetime
  167. ),
  168. },
  169. {
  170. title: "メール配信完了",
  171. value: formatDateTimeStr(order.status_receipt_email_send_datetime),
  172. },
  173. ];
  174. }, [order]);
  175. const downloadUrl = useMemo(() => {
  176. return getFullUrl(ApiId.DOWNLOAD_RECEIPT_LETTER) + "?id=" + order?.id;
  177. }, [order]);
  178. useEffect(() => {
  179. setHeaderTitle("領収証発行依頼");
  180. setTabs(null);
  181. fetch();
  182. }, []);
  183. useEffect(() => {
  184. setShowBackDrop(sending);
  185. }, [sending]);
  186. return (
  187. <>
  188. <Box>
  189. <Grid container spacing={2}>
  190. <Grid item xs={12}>
  191. <Stack direction="row" spacing={2}>
  192. <Button onClick={() => navigate(-1)}>戻る</Button>
  193. </Stack>
  194. </Grid>
  195. <Grid item xs={4}>
  196. <Paper elevation={0} sx={{ border: "1px solid" }}>
  197. <Stack spacing={2}>
  198. <Typography
  199. variant="h6"
  200. fontWeight="bold"
  201. sx={{ my: 2, textAlign: "center" }}
  202. >
  203. 依頼内容
  204. </Typography>
  205. <SimpleDataList data={orderInfo} />
  206. <Divider sx={{ my: 2 }} />
  207. <Typography
  208. variant="subtitle1"
  209. sx={{ my: 2, textAlign: "center" }}
  210. >
  211. 領収証情報
  212. </Typography>
  213. <SimpleDataList data={receiptInfo} />
  214. </Stack>
  215. </Paper>
  216. </Grid>
  217. <Grid item xs={4}>
  218. <Paper elevation={0} sx={{ pb: 2, border: "1px solid" }}>
  219. <Stack spacing={2}>
  220. <Typography
  221. variant="h6"
  222. fontWeight="bold"
  223. sx={{ my: 2, textAlign: "center" }}
  224. >
  225. 郵送管理
  226. </Typography>
  227. <SimpleDataList data={mailStatus1} />
  228. {hasMailOrder && (
  229. <>
  230. <Divider sx={{ my: 2 }} />
  231. <Typography
  232. variant="subtitle1"
  233. sx={{ my: 2, textAlign: "center" }}
  234. >
  235. 郵送先
  236. </Typography>
  237. <SimpleDataList data={mailStatus2} />
  238. <Divider />
  239. <Stack direction="row" spacing={2} sx={{ px: 2 }}>
  240. <Button
  241. variant="contained"
  242. href={downloadUrl}
  243. target="_blank"
  244. >
  245. 印字
  246. </Button>
  247. <Button
  248. variant="contained"
  249. onClick={postCompleteDialog.open}
  250. >
  251. 投函完了
  252. </Button>
  253. </Stack>
  254. {postCompleteDialog.element}
  255. </>
  256. )}
  257. </Stack>
  258. </Paper>
  259. </Grid>
  260. <Grid item xs={4}>
  261. <Paper elevation={0} sx={{ border: "1px solid" }}>
  262. <Stack spacing={2}>
  263. <Typography
  264. variant="h6"
  265. fontWeight="bold"
  266. sx={{ my: 2, textAlign: "center" }}
  267. >
  268. 各種アクション日時
  269. </Typography>
  270. <SimpleDataList data={actionDatetimes} />
  271. </Stack>
  272. </Paper>
  273. </Grid>
  274. </Grid>
  275. </Box>
  276. {changeHandlerDialog.element}
  277. </>
  278. );
  279. }