Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

306 lines
9.0KB

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