選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

302 行
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 (
  177. getFullUrl(ApiId.HT_CUSTOM_DOWNLOAD_RECEIPT_LETTER) + "?id=" + order?.id
  178. );
  179. }, [order]);
  180. useEffect(() => {
  181. setHeaderTitle("領収証発行依頼");
  182. setTabs(null);
  183. fetch();
  184. }, []);
  185. useEffect(() => {
  186. setShowBackDrop(sending);
  187. }, [sending]);
  188. return (
  189. <>
  190. <Box>
  191. <Grid container spacing={2}>
  192. <Grid item xs={12}>
  193. <Stack direction="row" spacing={2}>
  194. <Button onClick={() => navigate(-1)}>戻る</Button>
  195. </Stack>
  196. </Grid>
  197. <Grid item xs={4}>
  198. <Paper elevation={0} sx={{ border: "1px solid" }}>
  199. <Stack spacing={2}>
  200. <Typography
  201. variant="h6"
  202. fontWeight="bold"
  203. sx={{ my: 2, textAlign: "center" }}
  204. >
  205. 依頼内容
  206. </Typography>
  207. <SimpleDataList data={orderInfo} />
  208. <Divider sx={{ my: 2 }} />
  209. <Typography
  210. variant="subtitle1"
  211. sx={{ my: 2, textAlign: "center" }}
  212. >
  213. 領収証情報
  214. </Typography>
  215. <SimpleDataList data={receiptInfo} />
  216. </Stack>
  217. </Paper>
  218. </Grid>
  219. <Grid item xs={4}>
  220. <Paper elevation={0} sx={{ pb: 2, border: "1px solid" }}>
  221. <Stack spacing={2}>
  222. <Typography
  223. variant="h6"
  224. fontWeight="bold"
  225. sx={{ my: 2, textAlign: "center" }}
  226. >
  227. 郵送管理
  228. </Typography>
  229. <SimpleDataList data={mailStatus1} />
  230. {hasMailOrder && (
  231. <>
  232. <Divider sx={{ my: 2 }} />
  233. <Typography
  234. variant="subtitle1"
  235. sx={{ my: 2, textAlign: "center" }}
  236. >
  237. 郵送先
  238. </Typography>
  239. <SimpleDataList data={mailStatus2} />
  240. <Divider />
  241. <Stack direction="row" spacing={2} sx={{ px: 2 }}>
  242. <Button
  243. variant="contained"
  244. href={downloadUrl}
  245. target="_blank"
  246. >
  247. 印字
  248. </Button>
  249. <Button
  250. variant="contained"
  251. onClick={postCompleteDialog.open}
  252. >
  253. 投函完了
  254. </Button>
  255. </Stack>
  256. {postCompleteDialog.element}
  257. </>
  258. )}
  259. </Stack>
  260. </Paper>
  261. </Grid>
  262. <Grid item xs={4}>
  263. <Paper elevation={0} sx={{ border: "1px solid" }}>
  264. <Stack spacing={2}>
  265. <Typography
  266. variant="h6"
  267. fontWeight="bold"
  268. sx={{ my: 2, textAlign: "center" }}
  269. >
  270. 各種アクション日時
  271. </Typography>
  272. <SimpleDataList data={actionDatetimes} />
  273. </Stack>
  274. </Paper>
  275. </Grid>
  276. </Grid>
  277. </Box>
  278. {changeHandlerDialog.element}
  279. </>
  280. );
  281. }