瀏覽代碼

全体的に整備

develop
sosuke.iwabuchi 2 年之前
父節點
當前提交
fcfaf330f0
共有 14 個文件被更改,包括 561 次插入32 次删除
  1. +2
    -2
      src/api/app/index.ts
  2. +20
    -2
      src/api/app/receipt-issuing-order.ts
  3. +6
    -8
      src/api/custom/hello-techno/receipt-issuing-order.ts
  4. +2
    -0
      src/api/index.ts
  5. +46
    -7
      src/api/receipt-issuing-order.ts
  6. +4
    -0
      src/api/url.ts
  7. +0
    -1
      src/components/table/index.ts
  8. +61
    -0
      src/components/table/index.tsx
  9. +3
    -6
      src/contexts/AppContext.tsx
  10. +271
    -0
      src/pages/dashboard/receipt-issuing-order/detail.tsx
  11. +118
    -0
      src/pages/dashboard/receipt-issuing-order/hooks/useMailPostCompleteDialog.tsx
  12. +19
    -5
      src/pages/dashboard/receipt-issuing-order/list.tsx
  13. +8
    -0
      src/routes/index.tsx
  14. +1
    -1
      src/routes/path.ts

+ 2
- 2
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) => {


+ 20
- 2
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;


+ 6
- 8
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;



+ 2
- 0
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++,


+ 46
- 7
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;
};

+ 4
- 0
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";



+ 0
- 1
src/components/table/index.ts 查看文件

@@ -1 +0,0 @@
export { default as TableHeadCustom } from "./TableHeadCustom";

+ 61
- 0
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 (
<Table sx={tableSx}>
<TableBody>
{data.map(({ title, value, end }, index) => {
return (
<TableRow key={index}>
<TableCell
sx={{ borderRight: "1px solid rgba(224, 224, 224, 1)" }}
>
<Typography variant="body2">{title}</Typography>
</TableCell>
<TableCell>
<Stack direction="row" spacing={1}>
<TextFieldEx
value={value ?? ""}
readOnly
multiline
fullWidth
inputProps={{ style: { fontSize } }}
/>
{end}
</Stack>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
);
};

+ 3
- 6
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<ReceiptIssuingOrder | null>(null);
useState<AppReceiptIssuingOrder | null>(null);

const [tokenResult, setTokenResult] = useState<"cheking" | "ok" | "ng">(
"cheking"


+ 271
- 0
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<ReceiptIssuingOrderHTCustom | null>(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: <Button sx={{ minWidth: 80 }}>担当変更</Button>,
},
{ 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 (
<Box>
<Grid container spacing={2}>
<Grid item xs={12}>
<Stack direction="row" spacing={2}>
<Button onClick={() => navigate(-1)}>戻る</Button>
</Stack>
</Grid>
<Grid item xs={4}>
<Paper elevation={0} sx={{ border: "1px solid" }}>
<Stack spacing={2}>
<Typography
variant="h6"
fontWeight="bold"
sx={{ my: 2, textAlign: "center" }}
>
依頼内容
</Typography>
<SimpleDataList data={orderInfo} />
<Divider sx={{ my: 2 }} />
<Typography
variant="subtitle1"
sx={{ my: 2, textAlign: "center" }}
>
領収証情報
</Typography>
<SimpleDataList data={receiptInfo} />
</Stack>
</Paper>
</Grid>
<Grid item xs={4}>
<Paper elevation={0} sx={{ pb: 2, border: "1px solid" }}>
<Stack spacing={2}>
<Typography
variant="h6"
fontWeight="bold"
sx={{ my: 2, textAlign: "center" }}
>
郵送管理
</Typography>
<SimpleDataList data={mailStatus1} />
{hasMailOrder && (
<>
<Divider sx={{ my: 2 }} />
<Typography
variant="subtitle1"
sx={{ my: 2, textAlign: "center" }}
>
郵送先
</Typography>
<SimpleDataList data={mailStatus2} />
<Divider />
<Stack direction="row" spacing={2} sx={{ px: 2 }}>
<Button variant="contained" href={downloadUrl}>
印字
</Button>

<Button
variant="contained"
onClick={postCompleteDialog.open}
>
投函完了
</Button>
</Stack>
{postCompleteDialog.element}
</>
)}
</Stack>
</Paper>
</Grid>
<Grid item xs={4}>
<Paper elevation={0} sx={{ border: "1px solid" }}>
<Stack spacing={2}>
<Typography
variant="h6"
fontWeight="bold"
sx={{ my: 2, textAlign: "center" }}
>
各種アクション日時
</Typography>
<SimpleDataList data={actionDatetimes} />
</Stack>
</Paper>
</Grid>
</Grid>
</Box>
);
}

+ 118
- 0
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<FormProps>({
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 = (
<Dialog open={show} onClose={close}>
<DialogTitle>投稿完了登録</DialogTitle>

<FormProvider methods={form} onSubmit={form.handleSubmit(handleSubmit)}>
<DialogContent>
<RHFDatePicker name="date" label="投函完了日" />
</DialogContent>

<DialogActions>
<Button onClick={close}>CANCEL</Button>
<Button type="submit">OK</Button>
</DialogActions>
</FormProvider>
</Dialog>
);

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,
};
}

+ 19
- 5
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<ReceiptIssuingOrder>();
const table = useTable<ReceiptIssuingOrderHTCustom>();

return (
<Box>
@@ -59,7 +61,7 @@ type FormProps = {
parking_name: string;
};
type CommonProps = {
table: UseTableReturn<ReceiptIssuingOrder>;
table: UseTableReturn<ReceiptIssuingOrderHTCustom>;
};
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 (
<TableRow hover sx={{ cursor: "pointer" }}>
<TableRow hover sx={{ cursor: "pointer" }} onClick={handleClick}>
<TableCell>{data.order_datetime}</TableCell>
<TableCell>{data.customer_name}</TableCell>
<TableCell>{data.parking_name}</TableCell>


+ 8
- 0
src/routes/index.tsx 查看文件

@@ -78,6 +78,11 @@ const DashboardRoutes = (): RouteObject => {
element: <ReceiptIssuingOrderList />,
target: UserRole.NORMAL_ADMIN,
},
{
pageId: PageID.DASHBOARD_RECEIPT_ISSUING_ORDER_DETAIL,
element: <ReceiptIssuingOrderDetail />,
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")));


+ 1
- 1
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",


Loading…
取消
儲存