diff --git a/src/api/app/index.ts b/src/api/app/index.ts
index e6c1459..fd02cfe 100644
--- a/src/api/app/index.ts
+++ b/src/api/app/index.ts
@@ -1,6 +1,6 @@
import { APICommonResponse, ApiId, HttpMethod, request } from "..";
-import { ReceiptIssuingOrder } from "../receipt-issuing-order";
import { getUrl } from "../url";
+import { AppReceiptIssuingOrder } from "./receipt-issuing-order";
export type CheckTokenRequest = {
access_token: string;
@@ -8,7 +8,7 @@ export type CheckTokenRequest = {
export type CheckTokenResponse = {
data: {
- receipt_issuing_order: ReceiptIssuingOrder;
+ receipt_issuing_order: AppReceiptIssuingOrder;
};
} & APICommonResponse;
export const checkToken = async (data: CheckTokenRequest) => {
diff --git a/src/api/app/receipt-issuing-order.ts b/src/api/app/receipt-issuing-order.ts
index ee55a34..2533efe 100644
--- a/src/api/app/receipt-issuing-order.ts
+++ b/src/api/app/receipt-issuing-order.ts
@@ -1,7 +1,25 @@
-import { APICommonResponse, ApiId, HttpMethod, makeParam, request } from "..";
-import { ReceiptIssuingOrder } from "../receipt-issuing-order";
+import { ApiId, HttpMethod, makeParam, request } from "..";
import { getUrl } from "../url";
+export type AppReceiptIssuingOrder = {
+ id: string;
+
+ access_token_expires_at: string;
+
+ receipt_use_date?: string;
+ receipt_shop_name?: string;
+ receipt_issuer?: string;
+ receipt_purpose?: string;
+ receipt_name?: string;
+ receipt_amount?: string;
+ confirmed: boolean;
+
+ status_order_mail_datetime?: string;
+ status_mail_post_date?: string;
+
+ updated_at: string;
+};
+
// 領収証確定
export type ConfirmRequest = {
id: string;
diff --git a/src/api/custom/hello-techno/receipt-issuing-order.ts b/src/api/custom/hello-techno/receipt-issuing-order.ts
index fb52a3b..4ba6f47 100644
--- a/src/api/custom/hello-techno/receipt-issuing-order.ts
+++ b/src/api/custom/hello-techno/receipt-issuing-order.ts
@@ -5,6 +5,7 @@ import {
makeFormData,
request,
} from "api";
+import { ReceiptIssuingOrder } from "api/receipt-issuing-order";
import { getUrl } from "api/url";
export type HTCustomer = {
@@ -50,19 +51,16 @@ export const createReceiptIssuingOrder = async (
return res;
};
-export type ReceiptIssuingOrder = {
- id: string;
- order_datetime: string;
+export type ReceiptIssuingOrderHTCustom = {
customer_code: string;
parking_management_code: string;
customer_name: string;
parking_name: string;
- status_name: string;
- handler_id: string;
- handler_name: string;
-};
+ adjust_seq_no?: number;
+} & ReceiptIssuingOrder;
export type ReceiptIssuingOrdersRequest = {
+ id?: string;
customer_code?: string;
customer_name?: string;
parking_management_code?: string;
@@ -71,7 +69,7 @@ export type ReceiptIssuingOrdersRequest = {
export type ReceiptIssuingOrdersResponse = {
data: {
- records: ReceiptIssuingOrder[];
+ records: ReceiptIssuingOrderHTCustom[];
};
} & APICommonResponse;
diff --git a/src/api/index.ts b/src/api/index.ts
index 0c820a1..3886998 100644
--- a/src/api/index.ts
+++ b/src/api/index.ts
@@ -24,6 +24,8 @@ export const ApiId = {
RECEIPT_ISSUING_ORDERS: id++,
RECEIPT_ISSUING_ORDER: id++,
RECEIPT_ISSUING_ORDER_CREATE: id++,
+ RECEIPT_ISSUING_ORDER_MAIL_POST_COMPLETE: id++,
+ DOWNLOAD_RECEIPT_LETTER: id++,
// FOR CUSTOM
HT_CUSTOM_CUSTOMERS: id++,
diff --git a/src/api/receipt-issuing-order.ts b/src/api/receipt-issuing-order.ts
index 5707e09..47e0003 100644
--- a/src/api/receipt-issuing-order.ts
+++ b/src/api/receipt-issuing-order.ts
@@ -3,19 +3,42 @@ import { getUrl } from "./url";
export type ReceiptIssuingOrder = {
id: string;
+ order_datetime: string;
+ status_name: string;
+ handler_id: string;
+ handler_name: string;
+ summary_key1?: string;
+ summary_key2?: string;
+ status_done: boolean;
+ contract_id: string;
- access_token_expires_at: string;
-
+ status_sms_send_datetime?: string;
+ status_first_access_datetime?: string;
+ status_receipt_confirm_datetime?: string;
+ status_order_mail_datetime?: string;
+ status_mail_download_datetime?: string;
+ status_mail_post_date?: string;
+ status_receipt_download_datetime?: string;
+ status_receipt_email_send_order_datetime?: string;
+ status_receipt_email_send_datetime?: string;
+ sms_phone_number?: string;
+ sms_send_success?: boolean;
+ receipt_no?: string;
receipt_use_date?: string;
receipt_shop_name?: string;
receipt_issuer?: string;
receipt_purpose?: string;
receipt_name?: string;
- receipt_amount?: string;
- confirmed: boolean;
-
- status_order_mail_datetime?: string;
- status_mail_post_date?: string;
+ receipt_invoice_no?: string;
+ receipt_amount?: number;
+ email?: string;
+ mail_pref_code?: string;
+ mail_zip_code?: string;
+ mail_address1?: string;
+ mail_address2?: string;
+ mail_address3?: string;
+ mail_name?: string;
+ memo?: string;
updated_at: string;
};
@@ -41,3 +64,19 @@ export const getReceiptIssuingOrders = async (
});
return res;
};
+
+// 郵送投函完了登録 -----------------------
+export type MailPostCompleteRequest = {
+ id: string;
+ status_mail_post_date: Date | null;
+ timestamp: string;
+};
+
+export const completeMailPost = async (data: MailPostCompleteRequest) => {
+ const res = await request({
+ url: getUrl(ApiId.RECEIPT_ISSUING_ORDER_MAIL_POST_COMPLETE),
+ method: HttpMethod.POST,
+ data: makeParam(data),
+ });
+ return res;
+};
diff --git a/src/api/url.ts b/src/api/url.ts
index ab19838..2d5273c 100644
--- a/src/api/url.ts
+++ b/src/api/url.ts
@@ -12,6 +12,9 @@ const urls = {
[A.RECEIPT_ISSUING_ORDER_CONFIRM]: "receipt-issuing-order/confirm",
[A.DOWNLOAD_RECEIPT]: "receipt/download",
[A.RECEIPT_ISSUING_ORDER_MAIL_ORDER]: "receipt-issuing-order/mail-order",
+ [A.RECEIPT_ISSUING_ORDER_MAIL_POST_COMPLETE]:
+ "receipt-issuing-order/mail-complete",
+ [A.DOWNLOAD_RECEIPT_LETTER]: "receipt-letter/download",
[A.RECEIPT_ISSUING_ORDERS]: "receipt-issuing-orders",
@@ -28,6 +31,7 @@ const urls = {
const prefixs = {
[A.CSRF_TOKEN]: "",
[A.DOWNLOAD_RECEIPT]: "",
+ [A.DOWNLOAD_RECEIPT_LETTER]: "",
};
const DEFAULT_API_URL_PREFIX = "api";
diff --git a/src/components/table/index.ts b/src/components/table/index.ts
deleted file mode 100644
index 8ef8635..0000000
--- a/src/components/table/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { default as TableHeadCustom } from "./TableHeadCustom";
diff --git a/src/components/table/index.tsx b/src/components/table/index.tsx
new file mode 100644
index 0000000..e2ca244
--- /dev/null
+++ b/src/components/table/index.tsx
@@ -0,0 +1,61 @@
+import {
+ Button,
+ Stack,
+ SxProps,
+ Table,
+ TableBody,
+ TableCell,
+ TableRow,
+ Typography,
+ useTheme,
+} from "@mui/material";
+import TextFieldEx from "components/form/TextFieldEx";
+import { ReactNode, useEffect, useMemo } from "react";
+
+export { default as TableHeadCustom } from "./TableHeadCustom";
+
+type SimpleDataListProps = {
+ data: {
+ title: string;
+ value?: string;
+ end?: ReactNode;
+ }[];
+ tableSx?: SxProps;
+};
+export const SimpleDataList = ({ data, tableSx }: SimpleDataListProps) => {
+ const { typography } = useTheme();
+
+ const fontSize = useMemo(() => {
+ return typography.body2.fontSize;
+ }, [typography]);
+
+ return (
+
+
+ {data.map(({ title, value, end }, index) => {
+ return (
+
+
+ {title}
+
+
+
+
+ {end}
+
+
+
+ );
+ })}
+
+
+ );
+};
diff --git a/src/contexts/AppContext.tsx b/src/contexts/AppContext.tsx
index 8801921..412e9cb 100644
--- a/src/contexts/AppContext.tsx
+++ b/src/contexts/AppContext.tsx
@@ -1,9 +1,6 @@
import { HasChildren } from "@types";
import { checkToken } from "api/app";
-import {
- ReceiptIssuingOrder,
- getReceiptIssuingOrders,
-} from "api/receipt-issuing-order";
+import { AppReceiptIssuingOrder } from "api/app/receipt-issuing-order";
import { PageID } from "codes/page";
import useAPICall from "hooks/useAPICall";
import useNavigateCustom from "hooks/useNavigateCustom";
@@ -14,7 +11,7 @@ import { getPath } from "routes/path";
type App = {
token: string;
tokenResult: "cheking" | "ok" | "ng";
- receiptIssuingOrder: ReceiptIssuingOrder | null;
+ receiptIssuingOrder: AppReceiptIssuingOrder | null;
setToken: (token: string) => void;
fetch: VoidFunction;
navigateToHome: VoidFunction;
@@ -38,7 +35,7 @@ export function AppContextProvider({ children }: Props) {
const [token, _setToken] = useState("");
const [receiptIssuingOrder, setReceiptIssuingOrder] =
- useState(null);
+ useState(null);
const [tokenResult, setTokenResult] = useState<"cheking" | "ok" | "ng">(
"cheking"
diff --git a/src/pages/dashboard/receipt-issuing-order/detail.tsx b/src/pages/dashboard/receipt-issuing-order/detail.tsx
new file mode 100644
index 0000000..30628ab
--- /dev/null
+++ b/src/pages/dashboard/receipt-issuing-order/detail.tsx
@@ -0,0 +1,271 @@
+import {
+ Box,
+ Button,
+ Divider,
+ Grid,
+ Paper,
+ Stack,
+ Typography,
+} from "@mui/material";
+import {
+ ReceiptIssuingOrderHTCustom,
+ getReceiptIssuingOrders,
+} from "api/custom/hello-techno/receipt-issuing-order";
+import { PageID } from "codes/page";
+import { getPrefName } from "codes/prefcode";
+import { SimpleDataList } from "components/table";
+import useAPICall from "hooks/useAPICall";
+import useBackDrop from "hooks/useBackDrop";
+import useDashboard from "hooks/useDashBoard";
+import useNavigateCustom from "hooks/useNavigateCustom";
+import useSnackbarCustom from "hooks/useSnackbarCustom";
+import { isNumber } from "lodash";
+import { useEffect, useMemo, useState } from "react";
+import { useParams } from "react-router-dom";
+import { sprintf } from "sprintf-js";
+import { formatDateStr, formatDateTimeStr } from "utils/datetime";
+import useMailPostCompleteDialog from "./hooks/useMailPostCompleteDialog";
+import { getFullUrl } from "api/url";
+import { ApiId } from "api";
+
+export default function ReceiptIssuingOrderDetail() {
+ const { setHeaderTitle, setTabs } = useDashboard(
+ PageID.DASHBOARD_RECEIPT_ISSUING_ORDER_DETAIL
+ );
+
+ const { navigate } = useNavigateCustom();
+
+ const { error } = useSnackbarCustom();
+
+ const { id: receiptIssuingOrderId } = useParams();
+
+ const { setShowBackDrop } = useBackDrop();
+
+ const [order, setOrder] = useState(null);
+
+ const postCompleteDialog = useMailPostCompleteDialog(order, () => {
+ fetch();
+ });
+
+ const { callAPI, sending } = useAPICall({
+ apiMethod: getReceiptIssuingOrders,
+ onSuccess: (res) => {
+ const target = res.data.records[0];
+ if (target) {
+ setOrder(target);
+ }
+ },
+ onFailed: () => {
+ error("情報取得失敗");
+ navigate(-1);
+ },
+ });
+
+ const fetch = () => {
+ if (receiptIssuingOrderId) {
+ callAPI({
+ id: receiptIssuingOrderId,
+ });
+ }
+ };
+
+ const hasMailOrder = useMemo(() => {
+ return !!order?.status_order_mail_datetime;
+ }, [order]);
+ const orderInfo = useMemo(() => {
+ if (!order) return [];
+ return [
+ { title: "ステータス", value: order.status_name },
+ {
+ title: "担当者",
+ value: order.handler_name,
+ end: ,
+ },
+ { title: "SMS送信先", value: order.sms_phone_number },
+ { title: "依頼日", value: formatDateStr(order.order_datetime) },
+ { title: "運営会社", value: order.customer_name },
+ { title: "駐車場", value: order.parking_name },
+ { title: "利用日", value: formatDateStr(order.receipt_use_date) },
+ {
+ title: "精算連番",
+ value: isNumber(order.adjust_seq_no)
+ ? sprintf("%06d", order.adjust_seq_no)
+ : "-",
+ },
+ {
+ title: "金額",
+ value: isNumber(order.receipt_amount)
+ ? order.receipt_amount.toLocaleString() + "円"
+ : "-",
+ },
+ { title: "備考", value: order.memo },
+ ];
+ }, [order]);
+
+ const mailStatus1 = useMemo(() => {
+ if (!order) return [];
+ return [{ title: "郵送依頼", value: hasMailOrder ? "あり" : "なし" }];
+ }, [order]);
+ const mailStatus2 = useMemo(() => {
+ if (!order || !hasMailOrder) return [];
+ return [
+ { title: "郵便番号", value: "〒" + order.mail_zip_code },
+ { title: "都道府県", value: getPrefName(order.mail_pref_code ?? "") },
+ { title: "市区町村", value: order.mail_address1 },
+ { title: "番地等", value: order.mail_address2 },
+ { title: "建物名/部屋番号等", value: order.mail_address3 },
+ { title: "宛名", value: order.mail_name },
+ ];
+ }, [order]);
+
+ const receiptInfo = useMemo(() => {
+ if (!order) return [];
+ return [
+ { title: "領収証番号", value: order.receipt_no },
+ {
+ title: "宛名",
+ value: order.receipt_name,
+ },
+ ];
+ }, [order]);
+
+ const actionDatetimes = useMemo(() => {
+ if (!order) return [];
+ return [
+ {
+ title: "SMS送信",
+ value: formatDateTimeStr(order.status_sms_send_datetime),
+ },
+ {
+ title: "初回アクセス",
+ value: formatDateTimeStr(order.status_first_access_datetime),
+ },
+ {
+ title: "領収証確定",
+ value: formatDateTimeStr(order.status_receipt_confirm_datetime),
+ },
+ {
+ title: "郵送依頼",
+ value: formatDateTimeStr(order.status_order_mail_datetime),
+ },
+ { title: "郵送投函", value: formatDateStr(order.status_mail_post_date) },
+ {
+ title: "領収証ダウンロード",
+ value: formatDateTimeStr(order.status_receipt_download_datetime),
+ },
+ {
+ title: "メール配信依頼",
+ value: formatDateTimeStr(
+ order.status_receipt_email_send_order_datetime
+ ),
+ },
+ {
+ title: "メール配信完了",
+ value: formatDateTimeStr(order.status_receipt_email_send_datetime),
+ },
+ ];
+ }, [order]);
+
+ const downloadUrl = useMemo(() => {
+ return getFullUrl(ApiId.DOWNLOAD_RECEIPT_LETTER) + "?id=" + order?.id;
+ }, [order]);
+
+ useEffect(() => {
+ setHeaderTitle("領収証発行依頼");
+ setTabs(null);
+
+ fetch();
+ }, []);
+
+ useEffect(() => {
+ setShowBackDrop(sending);
+ }, [sending]);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ 依頼内容
+
+
+
+
+ 領収証情報
+
+
+
+
+
+
+
+
+
+ 郵送管理
+
+
+ {hasMailOrder && (
+ <>
+
+
+ 郵送先
+
+
+
+
+
+
+
+
+ {postCompleteDialog.element}
+ >
+ )}
+
+
+
+
+
+
+
+ 各種アクション日時
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/pages/dashboard/receipt-issuing-order/hooks/useMailPostCompleteDialog.tsx b/src/pages/dashboard/receipt-issuing-order/hooks/useMailPostCompleteDialog.tsx
new file mode 100644
index 0000000..fa980bb
--- /dev/null
+++ b/src/pages/dashboard/receipt-issuing-order/hooks/useMailPostCompleteDialog.tsx
@@ -0,0 +1,118 @@
+import { yupResolver } from "@hookform/resolvers/yup";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+} from "@mui/material";
+import {
+ ReceiptIssuingOrder,
+ completeMailPost,
+} from "api/receipt-issuing-order";
+import { FormProvider } from "components/hook-form";
+import RHFDatePicker from "components/hook-form/RHFDatePicker";
+import useAPICall from "hooks/useAPICall";
+import useBackDrop from "hooks/useBackDrop";
+import useSnackbarCustom from "hooks/useSnackbarCustom";
+import { useEffect, useState } from "react";
+import { useForm } from "react-hook-form";
+import { now } from "utils/datetime";
+import * as Yup from "yup";
+
+type FormProps = {
+ date: Date | null;
+};
+
+export default function useMailPostCompleteDialog(
+ order: ReceiptIssuingOrder | null,
+ onComplete?: VoidFunction
+) {
+ const [show, setShow] = useState(false);
+ const { setShowBackDrop } = useBackDrop();
+ const { success, error } = useSnackbarCustom();
+
+ const form = useForm({
+ defaultValues: {
+ date: now(),
+ },
+ resolver: yupResolver(
+ Yup.object().shape({
+ date: Yup.date()
+ .required("必須項目です")
+ .typeError("正しく入力してください"),
+ })
+ ),
+ });
+
+ const { callAPI, sending } = useAPICall({
+ apiMethod: completeMailPost,
+ onSuccess: () => {
+ success("登録しました");
+ setShow(false);
+ if (onComplete) {
+ onComplete();
+ }
+ },
+ onFailed: () => {
+ error("失敗しました");
+ },
+ });
+
+ const open = () => {
+ setShow(true);
+ };
+
+ const close = () => {
+ setShow(false);
+ };
+
+ const handleSubmit = (data: FormProps) => {
+ if (!order) return;
+ callAPI({
+ id: order.id,
+ status_mail_post_date: data.date,
+ timestamp: order.updated_at,
+ });
+ };
+
+ const element = (
+
+ );
+
+ useEffect(() => {
+ setShowBackDrop(sending);
+ }, [sending]);
+
+ useEffect(() => {
+ console.log(now());
+ // console.log(formatDateStr(now()));
+ // form.setValue('date', formatDateStr(now())
+ }, []);
+
+ return {
+ // param
+ show,
+
+ // Element
+ element,
+ // function
+
+ open,
+ close,
+ setShow,
+ };
+}
diff --git a/src/pages/dashboard/receipt-issuing-order/list.tsx b/src/pages/dashboard/receipt-issuing-order/list.tsx
index 6d18530..94bef6a 100644
--- a/src/pages/dashboard/receipt-issuing-order/list.tsx
+++ b/src/pages/dashboard/receipt-issuing-order/list.tsx
@@ -10,7 +10,7 @@ import {
} from "@mui/material";
import { Dictionary } from "@types";
import {
- ReceiptIssuingOrder,
+ ReceiptIssuingOrderHTCustom,
getReceiptIssuingOrders,
} from "api/custom/hello-techno/receipt-issuing-order";
import { PageID, TabID } from "codes/page";
@@ -20,10 +20,12 @@ import { SearchConditionContextProvider } from "contexts/SearchConditionContext"
import useAPICall from "hooks/useAPICall";
import useBackDrop from "hooks/useBackDrop";
import useDashboard from "hooks/useDashBoard";
+import useNavigateCustom from "hooks/useNavigateCustom";
import useSearchConditionContext from "hooks/useSearchConditionContext";
import useTable, { UseTableReturn } from "hooks/useTable";
import { useEffect } from "react";
import { useForm } from "react-hook-form";
+import { getPath } from "routes/path";
export default function ReceiptIssuingOrderList() {
const { setHeaderTitle, setTabs } = useDashboard(
@@ -44,7 +46,7 @@ export default function ReceiptIssuingOrderList() {
}
function Page() {
- const table = useTable();
+ const table = useTable();
return (
@@ -59,7 +61,7 @@ type FormProps = {
parking_name: string;
};
type CommonProps = {
- table: UseTableReturn;
+ table: UseTableReturn;
};
function SearchBox({ table }: CommonProps) {
const {
@@ -226,11 +228,23 @@ function TableBox({ table }: CommonProps) {
}
type RowProps = {
- data: ReceiptIssuingOrder;
+ data: ReceiptIssuingOrderHTCustom;
};
function Row({ data }: RowProps) {
+ const { navigateWhenChanged } = useNavigateCustom();
+
+ const handleClick = () => {
+ navigateWhenChanged(
+ getPath(PageID.DASHBOARD_RECEIPT_ISSUING_ORDER_DETAIL, {
+ query: {
+ id: data.id,
+ },
+ })
+ );
+ };
+
return (
-
+
{data.order_datetime}
{data.customer_name}
{data.parking_name}
diff --git a/src/routes/index.tsx b/src/routes/index.tsx
index 8e61d00..88d2283 100644
--- a/src/routes/index.tsx
+++ b/src/routes/index.tsx
@@ -78,6 +78,11 @@ const DashboardRoutes = (): RouteObject => {
element: ,
target: UserRole.NORMAL_ADMIN,
},
+ {
+ pageId: PageID.DASHBOARD_RECEIPT_ISSUING_ORDER_DETAIL,
+ element: ,
+ target: UserRole.NORMAL_ADMIN,
+ },
];
const children: RouteObject[] = useMemo(() => {
@@ -138,6 +143,9 @@ const ReceiptIssuingOrderCreate = Loadable(
const ReceiptIssuingOrderList = Loadable(
lazy(() => import("pages/dashboard/receipt-issuing-order/list"))
);
+const ReceiptIssuingOrderDetail = Loadable(
+ lazy(() => import("pages/dashboard/receipt-issuing-order/detail"))
+);
// その他 ---------------------------------
const Page403 = Loadable(lazy(() => import("pages/common/Page403")));
diff --git a/src/routes/path.ts b/src/routes/path.ts
index baf9a24..0dc12fe 100644
--- a/src/routes/path.ts
+++ b/src/routes/path.ts
@@ -54,7 +54,7 @@ const PATHS = {
[makePathKey(PageID.DASHBOARD_RECEIPT_ISSUING_ORDER_LIST)]:
"/dashboard/receipt-issusing-order/list/:page",
[makePathKey(PageID.DASHBOARD_RECEIPT_ISSUING_ORDER_DETAIL)]:
- "/dashboard/receipt-issusing-order/detail",
+ "/dashboard/receipt-issusing-order/detail/:id",
// その他
[makePathKey(PageID.PAGE_403)]: "403",