| @@ -46,10 +46,12 @@ | |||||
| }, | }, | ||||
| "dependencies": { | "dependencies": { | ||||
| "@kintone/rest-api-client": "^2.0.17", | "@kintone/rest-api-client": "^2.0.17", | ||||
| "@types/lodash": "^4.14.202", | |||||
| "@types/sprintf": "^0.1.2", | "@types/sprintf": "^0.1.2", | ||||
| "core-js": "^3.6.4", | "core-js": "^3.6.4", | ||||
| "date-fns": "^2.30.0", | "date-fns": "^2.30.0", | ||||
| "kintone-ui-component": "^1.14.0", | "kintone-ui-component": "^1.14.0", | ||||
| "lodash": "^4.17.21", | |||||
| "react": "^18.2.0", | "react": "^18.2.0", | ||||
| "react-dom": "^18.2.0", | "react-dom": "^18.2.0", | ||||
| "sprintf": "^0.1.5", | "sprintf": "^0.1.5", | ||||
| @@ -68,6 +68,16 @@ const getCallbackFillAmount = (record: 入金予定結果) => { | |||||
| }; | }; | ||||
| }; | }; | ||||
| // クエリパラメータよりフィールドに値をセットする | |||||
| const setData = (event: any, targets: string[]) => { | |||||
| const param = new URLSearchParams(location.search.replace("?", "")); | |||||
| targets.forEach((target) => { | |||||
| const value = param.get(target); | |||||
| if (value === null) return; | |||||
| event.record[target].value = value; | |||||
| event.record[target].lookup = true; | |||||
| }); | |||||
| }; | |||||
| (() => { | (() => { | ||||
| console.info("script build at " + process.env.BUILD_TIME); | console.info("script build at " + process.env.BUILD_TIME); | ||||
| @@ -81,4 +91,27 @@ const getCallbackFillAmount = (record: 入金予定結果) => { | |||||
| } | } | ||||
| } | } | ||||
| }); | }); | ||||
| kintone.events.on("app.record.create.show", (event) => { | |||||
| setData(event, [ | |||||
| 入金予定結果フィールド名.車室契約情報レコード番号, | |||||
| 入金予定結果フィールド名.初回振り込み関連申込レコード番号, | |||||
| ]); | |||||
| return event; | |||||
| }); | |||||
| kintone.events.on("app.record.create.submit.success", (event) => { | |||||
| const record = event.record as 入金予定結果; | |||||
| // 初回請求確定時にはメールを送信する | |||||
| if ( | |||||
| record[入金予定結果フィールド名.初回振り込み関連申込レコード番号].value | |||||
| ) { | |||||
| sendEmail(EmailID.申込受付, { | |||||
| season_ticket_contract_entry_record_no: Number( | |||||
| record[入金予定結果フィールド名.初回振り込み関連申込レコード番号] | |||||
| .value | |||||
| ), | |||||
| }); | |||||
| } | |||||
| }); | |||||
| })(); | })(); | ||||
| @@ -44,6 +44,7 @@ const 口座変更申請承認 = async (record: 各種申請) => { | |||||
| const customer = await get顧客マスタ({ | const customer = await get顧客マスタ({ | ||||
| 顧客コード: Number(record.顧客コード.value), | 顧客コード: Number(record.顧客コード.value), | ||||
| }); | }); | ||||
| if (customer === null) throw new Error("顧客不正"); | |||||
| // 顧客マスタへの反映 | // 顧客マスタへの反映 | ||||
| await client.record.updateRecord({ | await client.record.updateRecord({ | ||||
| @@ -141,7 +142,7 @@ const 利用者情報変更申請承認 = async (record: 各種申請) => { | |||||
| const customer = await get顧客マスタ({ | const customer = await get顧客マスタ({ | ||||
| 顧客コード: Number(record.顧客コード.value), | 顧客コード: Number(record.顧客コード.value), | ||||
| }); | }); | ||||
| if (customer === null) throw new Error("顧客不正"); | |||||
| await client.record.updateRecord({ | await client.record.updateRecord({ | ||||
| app: AppID.顧客マスタ, | app: AppID.顧客マスタ, | ||||
| id: customer.$id.value, | id: customer.$id.value, | ||||
| @@ -0,0 +1,12 @@ | |||||
| { | |||||
| "app": "", | |||||
| "scope": "ALL", | |||||
| "desktop": { | |||||
| "js": ["dist/定期申込予約.js"], | |||||
| "css":[] | |||||
| }, | |||||
| "mobile": { | |||||
| "js": [], | |||||
| "css":[] | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,62 @@ | |||||
| import { AppID } from "@/common/appids"; | |||||
| import { setHeaderButton } from "@/common/header-button"; | |||||
| import { CancelError } from "@/exception"; | |||||
| import { | |||||
| ShowConfirmDialog, | |||||
| SuccessDialog, | |||||
| WarningDialog, | |||||
| } from "@/middleware/swal"; | |||||
| import { getCreateUrl } from "@/rest-api/url"; | |||||
| import { 入金予定結果フィールド名 } from "@/types/入金予定結果"; | |||||
| import { 定期申込予約 } from "@/types/定期申込予約"; | |||||
| import { 申込 } from "./自動承認"; | |||||
| (() => { | |||||
| console.info("script build at " + process.env.BUILD_TIME); | |||||
| kintone.events.on("app.record.detail.show", (event) => { | |||||
| const record: 定期申込予約 = event.record; | |||||
| if (!record.auto_confirm_status.value) { | |||||
| setHeaderButton("自動承認", async () => { | |||||
| const confirm = await ShowConfirmDialog({ | |||||
| text: "承認しますか", | |||||
| }); | |||||
| if (!confirm.isConfirmed) return; | |||||
| try { | |||||
| const entry = new 申込(record); | |||||
| await entry.初期化(); | |||||
| await entry.選定(); | |||||
| await SuccessDialog.fire(); | |||||
| await WarningDialog.fire({ | |||||
| timer: 2000, | |||||
| timerProgressBar: true, | |||||
| text: "初回請求データを作成してください", | |||||
| }); | |||||
| const 契約 = entry.作成後契約取得(); | |||||
| if (!契約) throw new Error(); | |||||
| const param = new URLSearchParams({ | |||||
| [入金予定結果フィールド名.車室契約情報レコード番号]: 契約.$id.value, | |||||
| [入金予定結果フィールド名.初回振り込み関連申込レコード番号]: | |||||
| record.$id.value, | |||||
| }); | |||||
| const url = getCreateUrl(AppID.入金予定結果, param); | |||||
| console.log(url, param); | |||||
| window.open(url, "_blank"); | |||||
| location.reload(); | |||||
| } catch (e) { | |||||
| if (e instanceof CancelError) { | |||||
| console.log("canceled"); | |||||
| } else { | |||||
| throw e; | |||||
| } | |||||
| } | |||||
| }); | |||||
| } | |||||
| }); | |||||
| })(); | |||||
| @@ -0,0 +1,8 @@ | |||||
| import { dateParse, now } from "@/common/datetime"; | |||||
| import { 車室契約情報 } from "@/types/車室契約情報"; | |||||
| export const 初回請求情報取得 = (車室契約情報: 車室契約情報) => { | |||||
| const 利用開始日 = dateParse(車室契約情報.契約日.value); | |||||
| const 今日 = now(); | |||||
| 今日.setHours(0, 0, 0, 0); | |||||
| }; | |||||
| @@ -0,0 +1,251 @@ | |||||
| import { AppID } from "@/common/appids"; | |||||
| import { makeRecordData } from "@/common/rest-api-client"; | |||||
| import { 契約状況同期 } from "@/logic/契約状況同期"; | |||||
| import { | |||||
| ConfirmDialog, | |||||
| ShowConfirmDialog, | |||||
| showLoadingDialog, | |||||
| } from "@/middleware/swal"; | |||||
| import { EmailID, sendEmail } from "@/mypage/メール"; | |||||
| import { BulkRequest } from "@/rest-api/bulk"; | |||||
| import { getDetailUrl } from "@/rest-api/url"; | |||||
| import { get自動承認グループ } from "@/rest-api/自動承認グループ"; | |||||
| import { get車室契約情報, get車室契約情報一覧 } from "@/rest-api/車室契約情報"; | |||||
| import { get車室情報一覧 } from "@/rest-api/車室情報2"; | |||||
| import { | |||||
| getNextSMBC番号, | |||||
| getNext顧客コード, | |||||
| get顧客マスタ, | |||||
| } from "@/rest-api/顧客マスタ"; | |||||
| import { | |||||
| 定期申込予約, | |||||
| 定期申込予約フィールド名, | |||||
| 状態Dropdown, | |||||
| 自動承認ステータスDropdown, | |||||
| } from "@/types/定期申込予約"; | |||||
| import { 自動承認グループ } from "@/types/自動承認グループ"; | |||||
| import { 車室契約情報, 車室契約情報フィールド名 } from "@/types/車室契約情報"; | |||||
| import { 車室情報2 } from "@/types/車室情報2"; | |||||
| import { 顧客マスタフィールド名 } from "@/types/顧客マスタ"; | |||||
| import { sprintf } from "sprintf"; | |||||
| import { CancelError } from "../../exception"; | |||||
| import { 入金予定結果フィールド名 } from "@/types/入金予定結果"; | |||||
| import { dateParse, now } from "@/common/datetime"; | |||||
| export class 申込 { | |||||
| private 定期申込予約: 定期申込予約; | |||||
| private 初期化済み: boolean = false; | |||||
| private 顧客情報: { | |||||
| 顧客コード: number; | |||||
| } | null = null; | |||||
| private 車室一覧: 車室情報2[] = []; | |||||
| private 契約一覧: 車室契約情報[] = []; | |||||
| private 自動承認グループ: 自動承認グループ | null = null; | |||||
| private 作成後契約: 車室契約情報 | null = null; | |||||
| private requests: BulkRequest = new BulkRequest(); | |||||
| constructor(定期申込予約: 定期申込予約) { | |||||
| this.定期申込予約 = 定期申込予約; | |||||
| } | |||||
| async 初期化() { | |||||
| // 車室情報の取得 | |||||
| await this.契約対象車室取得(); | |||||
| // 対象のプランデータ取得 | |||||
| await this.契約情報取得(); | |||||
| // 自動承認データの取得 | |||||
| await this.自動承認グループ取得(); | |||||
| this.初期化済み = true; | |||||
| return this; | |||||
| } | |||||
| async 選定() { | |||||
| // 空き車室の特定 | |||||
| const target = this.選定情報取得(); | |||||
| // 顧客マスタの作成/取得 | |||||
| await this.顧客マスタ取得(); | |||||
| // 契約の作成 | |||||
| await this.契約情報作成(target); | |||||
| // 申込データの更新 | |||||
| await this.申込情報完了(); | |||||
| // データ保存 | |||||
| await this.save(); | |||||
| await 契約状況同期( | |||||
| this.定期申込予約.駐車場.value, | |||||
| Number(target.車室番号.value) | |||||
| ); | |||||
| } | |||||
| 選定情報取得() { | |||||
| return this.対象車室取得(); | |||||
| } | |||||
| 作成後契約取得() { | |||||
| return this.作成後契約; | |||||
| } | |||||
| private async 契約対象車室取得() { | |||||
| if (!this.定期申込予約.駐車場.value) { | |||||
| throw new Error("駐車場名の設定をしてください"); | |||||
| } | |||||
| this.車室一覧 = await get車室情報一覧({ | |||||
| 駐車場名: this.定期申込予約.駐車場.value, | |||||
| }); | |||||
| } | |||||
| private async 契約情報取得() { | |||||
| if (!this.定期申込予約.駐車場.value) { | |||||
| throw new Error("駐車場名の設定をしてください"); | |||||
| } | |||||
| this.契約一覧 = await get車室契約情報一覧({ | |||||
| 駐車場名: this.定期申込予約.駐車場.value, | |||||
| 契約中のみ: true, | |||||
| }); | |||||
| } | |||||
| private async 自動承認グループ取得() { | |||||
| if (!this.定期申込予約.定期駐車場プラン.value) { | |||||
| throw new Error("プラン名の設定をしてください"); | |||||
| } | |||||
| this.自動承認グループ = await get自動承認グループ( | |||||
| this.定期申込予約.定期駐車場プラン.value | |||||
| ); | |||||
| } | |||||
| private 対象車室取得() { | |||||
| if (!this.初期化済み) { | |||||
| throw new Error("実装エラー 未初期化"); | |||||
| } | |||||
| const target = this.自動承認グループ?.対象車室番号.value | |||||
| .filter(({ value: 定義 }) => { | |||||
| // 自動承認車室でない場合は対象外とする | |||||
| if (定義.自動承認スキップ.value.length !== 0) return false; | |||||
| // 契約中の車室は対象外とする | |||||
| const 同一車室の契約中情報: 車室契約情報 | undefined = | |||||
| this.契約一覧.find((契約) => { | |||||
| return 契約.車室番号.value === 定義.車室番号.value; | |||||
| }); | |||||
| if (!!同一車室の契約中情報) return false; | |||||
| return true; | |||||
| }) | |||||
| .sort((a, b) => { | |||||
| return Number(a.value.割当順.value) < Number(b.value.割当順.value) | |||||
| ? -1 | |||||
| : 1; | |||||
| }) | |||||
| .find(() => true); | |||||
| if (!target) { | |||||
| throw new Error("空き車室がありません"); | |||||
| } | |||||
| const 車室番号 = Number(target.value.車室番号.value); | |||||
| const 車室 = this.車室一覧.find((room) => { | |||||
| return Number(room.車室番号.value) === 車室番号; | |||||
| }); | |||||
| if (!車室) { | |||||
| throw new Error("車室がありません"); | |||||
| } | |||||
| return 車室; | |||||
| } | |||||
| private async 顧客マスタ取得() { | |||||
| const customer = await get顧客マスタ({ | |||||
| メールアドレス: this.定期申込予約.メールアドレス.value, | |||||
| 必須: false, | |||||
| }); | |||||
| if (customer) { | |||||
| const confirm = await ShowConfirmDialog({ | |||||
| html: sprintf( | |||||
| "<p>既存顧客<a href='%s' target='_blank'>[%s]</a>様へ契約を追加しますか</p>", | |||||
| getDetailUrl(AppID.顧客マスタ, customer.$id.value), | |||||
| customer.CustomerName.value | |||||
| ), | |||||
| }); | |||||
| if (!confirm.isConfirmed) throw new CancelError(); | |||||
| this.顧客情報 = { | |||||
| 顧客コード: Number(customer[顧客マスタフィールド名.顧客コード].value), | |||||
| }; | |||||
| } else { | |||||
| this.顧客マスタ作成(); | |||||
| } | |||||
| } | |||||
| private async 顧客マスタ作成() { | |||||
| const F = 顧客マスタフィールド名; | |||||
| const 顧客コード = await getNext顧客コード(); | |||||
| this.requests.create({ | |||||
| app: AppID.顧客マスタ, | |||||
| record: makeRecordData({ | |||||
| [F.顧客コード]: String(顧客コード), | |||||
| [F.顧客名]: this.定期申込予約.氏名.value, | |||||
| [F.顧客名カナ]: this.定期申込予約.フリガナ.value, | |||||
| [F.電話番号]: this.定期申込予約.電話番号.value, | |||||
| [F.メールアドレス]: this.定期申込予約.メールアドレス.value, | |||||
| [F.SMBC契約番号]: String(await getNextSMBC番号()), | |||||
| [F.支払方法]: "その他", | |||||
| }), | |||||
| }); | |||||
| this.顧客情報 = { | |||||
| 顧客コード, | |||||
| }; | |||||
| } | |||||
| private async 契約情報作成(対象車室: 車室情報2) { | |||||
| if (!this.顧客情報) throw new Error("顧客情報不正"); | |||||
| if (!this.定期申込予約) throw new Error("定期申込予約不正"); | |||||
| const F = 車室契約情報フィールド名; | |||||
| this.requests.create( | |||||
| { | |||||
| app: AppID.車室契約情報, | |||||
| record: makeRecordData({ | |||||
| [F.顧客コード]: String(this.顧客情報.顧客コード), | |||||
| [F.契約日]: this.get契約開始日(), | |||||
| [F.車両番号]: this.定期申込予約.車両番号.value, | |||||
| [F.車室番号]: 対象車室.車室番号.value, | |||||
| [F.プラン名]: this.定期申込予約.定期駐車場プラン.value, | |||||
| }), | |||||
| }, | |||||
| async ({ id }) => { | |||||
| if (!id) throw new Error(); | |||||
| this.作成後契約 = await get車室契約情報(Number(id)); | |||||
| } | |||||
| ); | |||||
| } | |||||
| private async 申込情報完了() { | |||||
| const F = 定期申込予約フィールド名; | |||||
| this.requests.update({ | |||||
| app: AppID.定期申込予約, | |||||
| id: this.定期申込予約.$id.value, | |||||
| record: makeRecordData({ | |||||
| [F.状態]: 状態Dropdown.承認_自動承認, | |||||
| [F.自動承認ステータス]: 自動承認ステータスDropdown.承認済, | |||||
| }), | |||||
| }); | |||||
| } | |||||
| private get契約開始日() { | |||||
| const 利用開始希望日 = this.定期申込予約.利用開始希望日.value; | |||||
| if (!利用開始希望日) throw new Error("利用開始希望日不正"); | |||||
| return 利用開始希望日; | |||||
| } | |||||
| private async save() { | |||||
| this.requests.debug(); | |||||
| await this.requests.save(); | |||||
| } | |||||
| } | |||||
| @@ -10,5 +10,7 @@ export const AppID = { | |||||
| 入金予定結果: APP_ID.入金予定結果, | 入金予定結果: APP_ID.入金予定結果, | ||||
| 各種申請: APP_ID.各種申請, | 各種申請: APP_ID.各種申請, | ||||
| 車室契約情報: APP_ID.車室契約情報, | 車室契約情報: APP_ID.車室契約情報, | ||||
| 車室情報2: APP_ID.車室情報2, | |||||
| 自動承認グループ: APP_ID.自動承認グループ, | |||||
| } as const; | } as const; | ||||
| export type AppID = (typeof AppID)[keyof typeof AppID]; | export type AppID = (typeof AppID)[keyof typeof AppID]; | ||||
| @@ -0,0 +1,54 @@ | |||||
| import { format, isValid, parse, parseISO } from "date-fns"; | |||||
| export const DEFAULT_DATE_FORMAT = "yyyy-MM-dd"; | |||||
| export const DEFAULT_DATE_TIME_FORMAT = "yyyy/MM/dd HH:mm:ss"; | |||||
| export const DEFAULT_DATE_TIME_FORMAT_ANOTHER1 = "yyyy-MM-dd HH:mm:ss"; | |||||
| export const DEFAULT_YYYYMM_FORMAT = "yyyyMM"; | |||||
| type Input = Date | string | null | undefined; | |||||
| export const formatDateStr = (source: Input) => { | |||||
| return formatToStr(source, DEFAULT_DATE_FORMAT); | |||||
| }; | |||||
| export const formatDateTimeStr = (source: Date | string | null | undefined) => { | |||||
| return formatToStr(source, DEFAULT_DATE_TIME_FORMAT); | |||||
| }; | |||||
| export const formatYYYYMMStr = (source: Date | string | null | undefined) => { | |||||
| return formatToStr(source, DEFAULT_YYYYMM_FORMAT); | |||||
| }; | |||||
| const formatToStr = (source: Input, formatStr: string) => { | |||||
| if (source === null || source === undefined) return ""; | |||||
| if (source instanceof Date) return format(source, formatStr); | |||||
| return format(parseISO(source), formatStr); | |||||
| }; | |||||
| export const now = () => { | |||||
| return new Date(); | |||||
| }; | |||||
| export const nowStr = (): string => { | |||||
| return formatDateTimeStr(now()); | |||||
| }; | |||||
| export const dateParse = (source: Input): Date | null => { | |||||
| return parseFromFormat(source, DEFAULT_DATE_FORMAT); | |||||
| }; | |||||
| export const dateTimeParse = (source: Input): Date | null => { | |||||
| return ( | |||||
| parseFromFormat(source, DEFAULT_DATE_TIME_FORMAT) ?? | |||||
| parseFromFormat(source, DEFAULT_DATE_TIME_FORMAT_ANOTHER1) | |||||
| ); | |||||
| }; | |||||
| const parseFromFormat = (source: Input, format: string): Date | null => { | |||||
| if (source === null || source === undefined) return null; | |||||
| if (source instanceof Date) return source; | |||||
| const ret = parse(source, format, new Date()); | |||||
| if (isValid(ret)) { | |||||
| return ret; | |||||
| } | |||||
| return null; | |||||
| }; | |||||
| @@ -1,4 +1,13 @@ | |||||
| export const setFieldValue = (fieldCode: string, value: string | object) => { | |||||
| export type Field = { | |||||
| [fieldCode: string]: { | |||||
| value: unknown; | |||||
| }; | |||||
| }; | |||||
| export const setFieldValue = ( | |||||
| fieldCode: string, | |||||
| value: string | object | |||||
| ): Field => { | |||||
| return { | return { | ||||
| [fieldCode]: { | [fieldCode]: { | ||||
| value, | value, | ||||
| @@ -8,7 +17,7 @@ export const setFieldValue = (fieldCode: string, value: string | object) => { | |||||
| export const makeRecordData = (data: { | export const makeRecordData = (data: { | ||||
| [fieldCode: string]: string | object; | [fieldCode: string]: string | object; | ||||
| }) => { | |||||
| }): Field => { | |||||
| let ret = {}; | let ret = {}; | ||||
| Object.keys(data).forEach((fieldCode) => { | Object.keys(data).forEach((fieldCode) => { | ||||
| ret = { | ret = { | ||||
| @@ -7,6 +7,9 @@ export type KintoneConfig = { | |||||
| 入金予定結果: number; | 入金予定結果: number; | ||||
| 各種申請: number; | 各種申請: number; | ||||
| 車室契約情報: number; | 車室契約情報: number; | ||||
| 車室情報2: number; | |||||
| 自動承認グループ: number; | |||||
| 定期駐車場プランマスタ: number; | |||||
| }; | }; | ||||
| }; | }; | ||||
| @@ -21,6 +24,9 @@ export const kintoneConfig = (): KintoneConfig => { | |||||
| 入金予定結果: 272, | 入金予定結果: 272, | ||||
| 各種申請: 294, | 各種申請: 294, | ||||
| 車室契約情報: 253, | 車室契約情報: 253, | ||||
| 車室情報2: 279, | |||||
| 自動承認グループ: 286, | |||||
| 定期駐車場プランマスタ: 257, | |||||
| }, | }, | ||||
| }; | }; | ||||
| } else { | } else { | ||||
| @@ -34,6 +40,9 @@ export const kintoneConfig = (): KintoneConfig => { | |||||
| 入金予定結果: 272, | 入金予定結果: 272, | ||||
| 各種申請: 294, | 各種申請: 294, | ||||
| 車室契約情報: 253, | 車室契約情報: 253, | ||||
| 車室情報2: 279, | |||||
| 自動承認グループ: 286, | |||||
| 定期駐車場プランマスタ: 257, | |||||
| }, | }, | ||||
| }; | }; | ||||
| } | } | ||||
| @@ -0,0 +1 @@ | |||||
| export class CancelError extends Error {} | |||||
| @@ -0,0 +1,47 @@ | |||||
| import { AppID } from "@/common/appids"; | |||||
| import { makeRecordData } from "@/common/rest-api-client"; | |||||
| import { BulkRequest } from "@/rest-api/bulk"; | |||||
| import { get車室契約情報一覧 } from "@/rest-api/車室契約情報"; | |||||
| import { get車室情報一覧 } from "@/rest-api/車室情報2"; | |||||
| import { 状態Dropdown, 車室情報2フィールド名 } from "@/types/車室情報2"; | |||||
| export const 契約状況同期 = async (駐車場名: string, 車室番号?: number) => { | |||||
| await 車室情報契約項目同期(駐車場名, 車室番号); | |||||
| }; | |||||
| const 車室情報契約項目同期 = async (駐車場名: string, 車室番号?: number) => { | |||||
| const requests = new BulkRequest(); | |||||
| const 契約一覧 = await get車室契約情報一覧({ | |||||
| 駐車場名, | |||||
| 車室番号, | |||||
| 契約中のみ: true, | |||||
| }); | |||||
| const 車室一覧 = await get車室情報一覧({ | |||||
| 駐車場名, | |||||
| 車室番号, | |||||
| }); | |||||
| console.log({ 契約一覧, 車室一覧 }); | |||||
| 車室一覧.forEach((車室) => { | |||||
| const 契約 = 契約一覧.find((c) => c.車室番号.value === 車室.車室番号.value); | |||||
| requests.update({ | |||||
| app: AppID.車室情報2, | |||||
| id: 車室.$id.value, | |||||
| record: makeRecordData({ | |||||
| [車室情報2フィールド名.状態]: !!契約 | |||||
| ? 状態Dropdown.契約中 | |||||
| : 状態Dropdown.空き, | |||||
| [車室情報2フィールド名.契約レコード番号]: 契約?.$id.value ?? "", | |||||
| }), | |||||
| }); | |||||
| }); | |||||
| // 保存 | |||||
| if (!requests.isSaved()) { | |||||
| requests.debug(); | |||||
| await requests.save(); | |||||
| } | |||||
| }; | |||||
| @@ -1,5 +1,5 @@ | |||||
| import { delay } from "@/common/timer"; | import { delay } from "@/common/timer"; | ||||
| import Swal from "sweetalert2"; | |||||
| import Swal, { SweetAlertOptions } from "sweetalert2"; | |||||
| export const SuccessDialog = Swal.mixin({ | export const SuccessDialog = Swal.mixin({ | ||||
| icon: "success", | icon: "success", | ||||
| @@ -12,6 +12,9 @@ export const ErrorDialog = Swal.mixin({ | |||||
| icon: "error", | icon: "error", | ||||
| title: "エラーが発生しました", | title: "エラーが発生しました", | ||||
| }); | }); | ||||
| export const WarningDialog = Swal.mixin({ | |||||
| icon: "warning", | |||||
| }); | |||||
| export const ConfirmDialog = Swal.mixin({ | export const ConfirmDialog = Swal.mixin({ | ||||
| icon: "info", | icon: "info", | ||||
| @@ -20,6 +23,15 @@ export const ConfirmDialog = Swal.mixin({ | |||||
| cancelButtonText: "キャンセル", | cancelButtonText: "キャンセル", | ||||
| }); | }); | ||||
| export const ShowConfirmDialog = (param: SweetAlertOptions) => { | |||||
| return ConfirmDialog.fire(param).then((result) => { | |||||
| if (result.isConfirmed) { | |||||
| showLoadingDialog(); | |||||
| } | |||||
| return result; | |||||
| }); | |||||
| }; | |||||
| export const LoadingDialog = Swal.mixin({ | export const LoadingDialog = Swal.mixin({ | ||||
| title: "実行中...", | title: "実行中...", | ||||
| text: "画面を閉じないでください", | text: "画面を閉じないでください", | ||||
| @@ -35,7 +47,7 @@ export const LoadingDialog = Swal.mixin({ | |||||
| * 必ずawaitを入れて同期処理にすること | * 必ずawaitを入れて同期処理にすること | ||||
| * @param timer | * @param timer | ||||
| */ | */ | ||||
| export const showLoadingDialog = async (timer: number = 5000) => { | |||||
| export const showLoadingDialog = async (timer: number = 10 * 1000) => { | |||||
| LoadingDialog.fire({ | LoadingDialog.fire({ | ||||
| timer, | timer, | ||||
| }).then((result) => { | }).then((result) => { | ||||
| @@ -0,0 +1,106 @@ | |||||
| import { AppID } from "@/common/appids"; | |||||
| import { Field } from "@/common/rest-api-client"; | |||||
| import { delay } from "@/common/timer"; | |||||
| import { KintoneRestAPIClient } from "@kintone/rest-api-client"; | |||||
| import { chunk } from "lodash"; | |||||
| const UPDATE_PARAM = { | |||||
| method: "PUT", | |||||
| api: "/k/v1/record.json", | |||||
| } as const; | |||||
| const CREATE_PARAM = { | |||||
| method: "POST", | |||||
| api: "/k/v1/record.json", | |||||
| } as const; | |||||
| type Payload = { | |||||
| app: AppID; | |||||
| id?: string | number; | |||||
| query?: string; | |||||
| record: Field; | |||||
| }; | |||||
| type BulkRequestResponse = { id?: string; revision?: string }; | |||||
| export type RequestParam = { | |||||
| method: "POST" | "PUT"; | |||||
| api: string; | |||||
| payload: Payload; | |||||
| }; | |||||
| type Callback = (result: BulkRequestResponse) => Promise<void>; | |||||
| export class BulkRequest { | |||||
| private client: KintoneRestAPIClient; | |||||
| private requests: Array<RequestParam> = []; | |||||
| private callbacks: { | |||||
| [index: number]: Callback; | |||||
| } = {}; | |||||
| constructor() { | |||||
| this.client = new KintoneRestAPIClient({ | |||||
| baseUrl: location.origin, | |||||
| }); | |||||
| } | |||||
| update(payload: Payload, callback?: Callback) { | |||||
| const request: RequestParam = { | |||||
| ...UPDATE_PARAM, | |||||
| payload, | |||||
| }; | |||||
| this.requests.push(request); | |||||
| if (callback) { | |||||
| this.callbacks[this.requests.length - 1] = callback; | |||||
| } | |||||
| } | |||||
| create(payload: Payload, callback?: Callback) { | |||||
| const request: RequestParam = { | |||||
| ...CREATE_PARAM, | |||||
| payload, | |||||
| }; | |||||
| this.requests.push(request); | |||||
| if (callback) { | |||||
| this.callbacks[this.requests.length - 1] = callback; | |||||
| } | |||||
| } | |||||
| isSaved() { | |||||
| return this.requests.length === 0; | |||||
| } | |||||
| async save() { | |||||
| let results: BulkRequestResponse[] = []; | |||||
| for (const requests of chunk(this.requests, 20)) { | |||||
| const res = await this.client.bulkRequest({ requests }); | |||||
| results = [...results, ...res.results]; | |||||
| } | |||||
| await this.execCallback(results); | |||||
| this.clear(); | |||||
| return results; | |||||
| } | |||||
| private async execCallback(results: BulkRequestResponse[]) { | |||||
| for (const [index, result] of results.entries()) { | |||||
| if (index in this.callbacks) { | |||||
| console.log("exec callback", this.requests.at(index)); | |||||
| const callback = this.callbacks[index]; | |||||
| await callback(result); | |||||
| } | |||||
| } | |||||
| } | |||||
| clear() { | |||||
| this.requests = []; | |||||
| } | |||||
| debug() { | |||||
| console.log("BulkRequest debug", this, this.requests); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,53 @@ | |||||
| import { sprintf } from "sprintf"; | |||||
| type ORDER = "asc" | "desc"; | |||||
| type OrderCondition = { | |||||
| カラム: string; | |||||
| 並び: ORDER; | |||||
| }; | |||||
| export class QueryBuilder { | |||||
| private whereConditions: string[] = []; | |||||
| private order: OrderCondition[] = []; | |||||
| private _limit: number | null = null; | |||||
| where(カラム: string, 条件: string | number, 比較文字列: string = "=") { | |||||
| if (typeof 条件 === "string") { | |||||
| this.whereConditions.push( | |||||
| sprintf('%s %s "%s"', カラム, 比較文字列, 条件) | |||||
| ); | |||||
| } else { | |||||
| this.whereConditions.push(sprintf("%s %s %d", カラム, 比較文字列, 条件)); | |||||
| } | |||||
| return this; | |||||
| } | |||||
| orderBy(カラム: string, 並び: ORDER = "asc") { | |||||
| this.order.push({ | |||||
| カラム, | |||||
| 並び, | |||||
| }); | |||||
| return this; | |||||
| } | |||||
| limit(limit: number) { | |||||
| this._limit = limit; | |||||
| return this; | |||||
| } | |||||
| build(): string { | |||||
| let query = ""; | |||||
| query += this.whereConditions.join(" and ") + " "; | |||||
| this.order.forEach(({ カラム, 並び }) => { | |||||
| query += sprintf(" order by %s %s ", カラム, 並び); | |||||
| }); | |||||
| if (this._limit !== null) { | |||||
| query += sprintf(" limit %d ", this._limit); | |||||
| } | |||||
| console.log("QueryBuilder", query); | |||||
| return query; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,17 @@ | |||||
| import { AppID } from "@/common/appids"; | |||||
| import { sprintf } from "sprintf"; | |||||
| export const getDetailUrl = (app: AppID, レコード番号: string | number) => { | |||||
| if (typeof レコード番号 === "string") { | |||||
| レコード番号 = Number(レコード番号); | |||||
| } | |||||
| return sprintf("%s/k/%d/show#record=%d", location.origin, app, レコード番号); | |||||
| }; | |||||
| export const getCreateUrl = (app: AppID, param?: URLSearchParams) => { | |||||
| return sprintf( | |||||
| "%s/k/%d/edit?%s", | |||||
| location.origin, | |||||
| app, | |||||
| !!param ? param.toString() : "" | |||||
| ); | |||||
| }; | |||||
| @@ -0,0 +1,35 @@ | |||||
| import { AppID } from "@/common/appids"; | |||||
| import { | |||||
| 自動承認グループ, | |||||
| 自動承認グループフィールド名, | |||||
| } from "@/types/自動承認グループ"; | |||||
| import { KintoneRestAPIClient } from "@kintone/rest-api-client"; | |||||
| import { sprintf } from "sprintf"; | |||||
| const client = new KintoneRestAPIClient(); | |||||
| export const get自動承認グループ = async ( | |||||
| プラン名: string | |||||
| ): Promise<自動承認グループ> => { | |||||
| const query = sprintf( | |||||
| sprintf('%s = "%s"', 自動承認グループフィールド名.プラン名, プラン名) | |||||
| ); | |||||
| const { records } = await client.record.getRecords<自動承認グループ>({ | |||||
| app: AppID.自動承認グループ, | |||||
| query, | |||||
| }); | |||||
| if (records.length !== 1) { | |||||
| throw new Error( | |||||
| sprintf( | |||||
| "自動承認グループ取得数数エラー expect %d, actual %d query:%s", | |||||
| 1, | |||||
| records.length, | |||||
| query | |||||
| ) | |||||
| ); | |||||
| } | |||||
| return records[0]; | |||||
| }; | |||||
| @@ -1,6 +1,8 @@ | |||||
| import { AppID } from "@/common/appids"; | import { AppID } from "@/common/appids"; | ||||
| import { 車室契約情報 } from "@/types/車室契約情報"; | |||||
| import { formatDateStr, now } from "@/common/datetime"; | |||||
| import { 車室契約情報, 車室契約情報フィールド名 } from "@/types/車室契約情報"; | |||||
| import { KintoneRestAPIClient } from "@kintone/rest-api-client"; | import { KintoneRestAPIClient } from "@kintone/rest-api-client"; | ||||
| import { QueryBuilder } from "./query"; | |||||
| const client = new KintoneRestAPIClient(); | const client = new KintoneRestAPIClient(); | ||||
| @@ -14,3 +16,34 @@ export const get車室契約情報 = async ( | |||||
| return record; | return record; | ||||
| }; | }; | ||||
| type get車室契約情報一覧オプション = { | |||||
| 駐車場名?: string; | |||||
| 車室番号?: number | string; | |||||
| 契約中のみ?: boolean; | |||||
| }; | |||||
| export const get車室契約情報一覧 = async ({ | |||||
| 駐車場名, | |||||
| 車室番号, | |||||
| 契約中のみ, | |||||
| }: get車室契約情報一覧オプション): Promise<車室契約情報[]> => { | |||||
| const builder = new QueryBuilder(); | |||||
| if (駐車場名) { | |||||
| builder.where(車室契約情報フィールド名.定期駐車場名, 駐車場名); | |||||
| } | |||||
| if (車室番号) { | |||||
| builder.where(車室契約情報フィールド名.車室番号, 車室番号); | |||||
| } | |||||
| if (契約中のみ) { | |||||
| const todayStr = formatDateStr(now()); | |||||
| builder.where(車室契約情報フィールド名.解約日, todayStr, ">"); | |||||
| } | |||||
| const record = await client.record.getAllRecords<車室契約情報>({ | |||||
| app: AppID.車室契約情報, | |||||
| condition: builder.build(), | |||||
| }); | |||||
| return record; | |||||
| }; | |||||
| @@ -0,0 +1,31 @@ | |||||
| import { AppID } from "@/common/appids"; | |||||
| import { 車室情報2, 車室情報2フィールド名 } from "@/types/車室情報2"; | |||||
| import { KintoneRestAPIClient } from "@kintone/rest-api-client"; | |||||
| import { sprintf } from "sprintf"; | |||||
| import { QueryBuilder } from "./query"; | |||||
| const client = new KintoneRestAPIClient(); | |||||
| type get車室情報一覧オプション = { | |||||
| 駐車場名?: string; | |||||
| 車室番号?: number | string; | |||||
| }; | |||||
| export const get車室情報一覧 = async ({ | |||||
| 駐車場名, | |||||
| 車室番号, | |||||
| }: get車室情報一覧オプション): Promise<車室情報2[]> => { | |||||
| const builder = new QueryBuilder(); | |||||
| if (駐車場名) { | |||||
| builder.where(車室情報2フィールド名.駐車場名, 駐車場名); | |||||
| } | |||||
| if (車室番号) { | |||||
| builder.where(車室情報2フィールド名.車室番号, 車室番号); | |||||
| } | |||||
| const { records } = await client.record.getRecords<車室情報2>({ | |||||
| app: AppID.車室情報2, | |||||
| query: builder.build(), | |||||
| }); | |||||
| return records; | |||||
| }; | |||||
| @@ -1,47 +1,89 @@ | |||||
| import { AppID } from "@/common/appids"; | import { AppID } from "@/common/appids"; | ||||
| import { フィールド名 } from "@/types"; | |||||
| import { 顧客マスタ, 顧客マスタフィールド名 } from "@/types/顧客マスタ"; | import { 顧客マスタ, 顧客マスタフィールド名 } from "@/types/顧客マスタ"; | ||||
| import { KintoneRestAPIClient } from "@kintone/rest-api-client"; | import { KintoneRestAPIClient } from "@kintone/rest-api-client"; | ||||
| import { sprintf } from "sprintf"; | import { sprintf } from "sprintf"; | ||||
| import { QueryBuilder } from "./query"; | |||||
| const client = new KintoneRestAPIClient(); | const client = new KintoneRestAPIClient(); | ||||
| type Props = { | type Props = { | ||||
| レコード番号?: number; | レコード番号?: number; | ||||
| 顧客コード?: number; | 顧客コード?: number; | ||||
| メールアドレス?: string; | |||||
| 電話番号?: string; | |||||
| 必須?: boolean; | |||||
| }; | }; | ||||
| export const get顧客マスタ = async ({ | export const get顧客マスタ = async ({ | ||||
| レコード番号, | レコード番号, | ||||
| 顧客コード, | 顧客コード, | ||||
| }: Props): Promise<顧客マスタ> => { | |||||
| if (!!レコード番号) { | |||||
| const { record } = await client.record.getRecord<顧客マスタ>({ | |||||
| app: AppID.顧客マスタ, | |||||
| id: レコード番号, | |||||
| }); | |||||
| メールアドレス, | |||||
| 電話番号, | |||||
| 必須 = true, | |||||
| }: Props): Promise<顧客マスタ | null> => { | |||||
| const builder = new QueryBuilder(); | |||||
| return record; | |||||
| if (!!レコード番号) { | |||||
| builder.where(フィールド名.レコード番号, レコード番号); | |||||
| } | } | ||||
| if (!!顧客コード) { | if (!!顧客コード) { | ||||
| const query = sprintf( | |||||
| sprintf("%s = %d", 顧客マスタフィールド名.顧客コード, 顧客コード) | |||||
| ); | |||||
| builder.where(顧客マスタフィールド名.顧客コード, 顧客コード); | |||||
| } | |||||
| if (!!メールアドレス) { | |||||
| builder.where(顧客マスタフィールド名.メールアドレス, メールアドレス); | |||||
| } | |||||
| if (!!電話番号) { | |||||
| builder.where(顧客マスタフィールド名.電話番号, 電話番号); | |||||
| } | |||||
| const { records } = await client.record.getRecords<顧客マスタ>({ | |||||
| app: AppID.顧客マスタ, | |||||
| query, | |||||
| }); | |||||
| const { records } = await client.record.getRecords<顧客マスタ>({ | |||||
| app: AppID.顧客マスタ, | |||||
| query: builder.build(), | |||||
| }); | |||||
| if (records.length !== 1) { | |||||
| if (records.length === 0) { | |||||
| if (必須) { | |||||
| throw new Error( | throw new Error( | ||||
| sprintf( | |||||
| "顧客マスタ取得数エラー expect %d, actual %d", | |||||
| 1, | |||||
| records.length | |||||
| ) | |||||
| sprintf("顧客マスタ取得数エラー expect %d, actual %d", 1, 0) | |||||
| ); | ); | ||||
| } | } | ||||
| return records[0]; | |||||
| return null; | |||||
| } | |||||
| if (records.length !== 1) { | |||||
| throw new Error( | |||||
| sprintf("顧客マスタ取得数エラー expect %d, actual %d", 1, records.length) | |||||
| ); | |||||
| } | } | ||||
| return records[0]; | |||||
| }; | |||||
| throw new Error("get顧客マスタ 引数エラー"); | |||||
| export const getNext顧客コード = async () => { | |||||
| const query = sprintf( | |||||
| "order by %s desc limit 1", | |||||
| 顧客マスタフィールド名.顧客コード | |||||
| ); | |||||
| const { records } = await client.record.getRecords<顧客マスタ>({ | |||||
| app: AppID.顧客マスタ, | |||||
| query, | |||||
| }); | |||||
| if (records.length === 0) { | |||||
| return 1; | |||||
| } | |||||
| return Number(records[0][顧客マスタフィールド名.顧客コード].value) + 1; | |||||
| }; | |||||
| export const getNextSMBC番号 = async () => { | |||||
| const query = sprintf( | |||||
| "order by %s desc limit 1", | |||||
| 顧客マスタフィールド名.SMBC契約番号 | |||||
| ); | |||||
| const { records } = await client.record.getRecords<顧客マスタ>({ | |||||
| app: AppID.顧客マスタ, | |||||
| query, | |||||
| }); | |||||
| if (records.length === 0) { | |||||
| return 1; | |||||
| } | |||||
| return Number(records[0][顧客マスタフィールド名.SMBC契約番号].value) + 1; | |||||
| }; | }; | ||||
| @@ -1,7 +1,13 @@ | |||||
| import { KintoneRecordField } from "@kintone/rest-api-client"; | import { KintoneRecordField } from "@kintone/rest-api-client"; | ||||
| export const フィールド名 = { | |||||
| レコード番号: "$id", | |||||
| } as const; | |||||
| const F = フィールド名; | |||||
| export type AppRecord = { | export type AppRecord = { | ||||
| $id: KintoneRecordField.ID; | |||||
| [F.レコード番号]: KintoneRecordField.ID; | |||||
| $revision: KintoneRecordField.Revision; | $revision: KintoneRecordField.Revision; | ||||
| 作成者: KintoneRecordField.Creator; | 作成者: KintoneRecordField.Creator; | ||||
| レコード番号: KintoneRecordField.RecordNumber; | レコード番号: KintoneRecordField.RecordNumber; | ||||
| @@ -2,9 +2,15 @@ import { KintoneRecordField } from "@kintone/rest-api-client"; | |||||
| import { AppRecord } from "."; | import { AppRecord } from "."; | ||||
| const F = { | const F = { | ||||
| 車室契約情報レコード番号: "contract_record_number", | |||||
| 支払対象_利用_年: "target_year", | |||||
| 支払対象_利用_月: "target_month", | |||||
| 支払対象_利用_月間数: "target_term_month", | |||||
| 支払予定日: "payment_plan_date", | |||||
| 支払予定金額: "payment_plan_amount", | |||||
| 入金予定コード: "payment_plan_code", | |||||
| 入金日: "appropriation_date", | 入金日: "appropriation_date", | ||||
| 入金額: "appropriation_amount", | 入金額: "appropriation_amount", | ||||
| 支払予定金額: "payment_plan_amount", | |||||
| 残金: "remaining_amount", | 残金: "remaining_amount", | ||||
| 初回振り込み関連申込レコード番号: "first_payment_entry_record_no", | 初回振り込み関連申込レコード番号: "first_payment_entry_record_no", | ||||
| } as const; | } as const; | ||||
| @@ -23,18 +29,18 @@ export type 支払種別Dropdown = | |||||
| export const 入金予定結果フィールド名 = F; | export const 入金予定結果フィールド名 = F; | ||||
| export type 入金予定結果 = AppRecord & { | export type 入金予定結果 = AppRecord & { | ||||
| contract_record_number: KintoneRecordField.Number; | |||||
| payment_plan_date: KintoneRecordField.Date; | |||||
| payment_plan_code: KintoneRecordField.SingleLineText; | |||||
| [F.車室契約情報レコード番号]: KintoneRecordField.Number; | |||||
| [F.支払予定日]: KintoneRecordField.Date; | |||||
| [F.入金予定コード]: KintoneRecordField.SingleLineText; | |||||
| [F.残金]: KintoneRecordField.Number; | [F.残金]: KintoneRecordField.Number; | ||||
| [F.入金日]: KintoneRecordField.Date; | [F.入金日]: KintoneRecordField.Date; | ||||
| target_year: KintoneRecordField.SingleLineText; | |||||
| target_month: KintoneRecordField.SingleLineText; | |||||
| [F.支払対象_利用_年]: KintoneRecordField.SingleLineText; | |||||
| [F.支払対象_利用_月]: KintoneRecordField.SingleLineText; | |||||
| [F.入金額]: KintoneRecordField.Number; | [F.入金額]: KintoneRecordField.Number; | ||||
| payment_type: KintoneRecordField.Dropdown; | payment_type: KintoneRecordField.Dropdown; | ||||
| customer_name_kana: KintoneRecordField.SingleLineText; | customer_name_kana: KintoneRecordField.SingleLineText; | ||||
| [F.支払予定金額]: KintoneRecordField.Number; | [F.支払予定金額]: KintoneRecordField.Number; | ||||
| target_term_month: KintoneRecordField.SingleLineText; | |||||
| [F.支払対象_利用_月間数]: KintoneRecordField.SingleLineText; | |||||
| customer_name: KintoneRecordField.SingleLineText; | customer_name: KintoneRecordField.SingleLineText; | ||||
| parking_name: KintoneRecordField.SingleLineText; | parking_name: KintoneRecordField.SingleLineText; | ||||
| customer_code: KintoneRecordField.Number; | customer_code: KintoneRecordField.Number; | ||||
| @@ -3,6 +3,8 @@ import { AppRecord } from "."; | |||||
| const F = { | const F = { | ||||
| 状態: "status", | 状態: "status", | ||||
| 自動承認ステータス: "auto_confirm_status", | |||||
| 利用開始希望日: "利用開始希望日", | |||||
| } as const; | } as const; | ||||
| export const 状態Dropdown = { | export const 状態Dropdown = { | ||||
| @@ -18,6 +20,13 @@ export const 状態Dropdown = { | |||||
| } as const; | } as const; | ||||
| export type 状態Dropdown = (typeof 状態Dropdown)[keyof typeof 状態Dropdown]; | export type 状態Dropdown = (typeof 状態Dropdown)[keyof typeof 状態Dropdown]; | ||||
| export const 自動承認ステータスDropdown = { | |||||
| NONE: "", | |||||
| 承認済: "承認済", | |||||
| } as const; | |||||
| export type 自動承認ステータスDropdown = | |||||
| (typeof 自動承認ステータスDropdown)[keyof typeof 自動承認ステータスDropdown]; | |||||
| export const 定期申込予約フィールド名 = F; | export const 定期申込予約フィールド名 = F; | ||||
| export type 定期申込予約 = AppRecord & { | export type 定期申込予約 = AppRecord & { | ||||
| @@ -54,6 +63,6 @@ export type 定期申込予約 = AppRecord & { | |||||
| ParkingNaviプラン: KintoneRecordField.SingleLineText; | ParkingNaviプラン: KintoneRecordField.SingleLineText; | ||||
| 日割り分_月: KintoneRecordField.Number; | 日割り分_月: KintoneRecordField.Number; | ||||
| 支払方法: KintoneRecordField.Dropdown; | 支払方法: KintoneRecordField.Dropdown; | ||||
| auto_confirm_status: KintoneRecordField.SingleLineText; | |||||
| [F.自動承認ステータス]: KintoneRecordField.SingleLineText; | |||||
| [F.状態]: KintoneRecordField.Dropdown; | [F.状態]: KintoneRecordField.Dropdown; | ||||
| }; | }; | ||||
| @@ -0,0 +1,64 @@ | |||||
| import { KintoneRecordField } from "@kintone/rest-api-client"; | |||||
| import { AppRecord } from "."; | |||||
| const F = { | |||||
| プラン名: "key", | |||||
| } as const; | |||||
| // export const 支払種別Dropdown = { | |||||
| // 定期料金: "定期料金", | |||||
| // 保証金: "保証金", | |||||
| // 証明書郵送代: "証明書郵送代", | |||||
| // 事務手数料: "事務手数料", | |||||
| // 延滞金: "延滞金", | |||||
| // 余剰金: "余剰金", | |||||
| // } as const; | |||||
| // export type 支払種別Dropdown = | |||||
| // (typeof 支払種別Dropdown)[keyof typeof 支払種別Dropdown]; | |||||
| export const 定期駐車場プランマスタフィールド名 = F; | |||||
| export type 対象車室番号行データ = { | |||||
| 割当順: KintoneRecordField.Number; | |||||
| 車室番号: KintoneRecordField.SingleLineText; | |||||
| 利用中: KintoneRecordField.CheckBox; | |||||
| 自動承認スキップ: KintoneRecordField.CheckBox; | |||||
| }; | |||||
| export type 定期駐車場プランマスタ = AppRecord & { | |||||
| 備考: KintoneRecordField.MultiLineText; | |||||
| 状況: KintoneRecordField.RadioButton; | |||||
| 支払パターン: KintoneRecordField.Dropdown; | |||||
| 保証金: KintoneRecordField.Number; | |||||
| 収容台数: KintoneRecordField.Number; | |||||
| 住所_駐車場マスタ: KintoneRecordField.SingleLineText; | |||||
| パスカード保証金: KintoneRecordField.Number; | |||||
| 定期駐車場名: KintoneRecordField.SingleLineText; | |||||
| 駐車場名: KintoneRecordField.SingleLineText; | |||||
| key: KintoneRecordField.SingleLineText; | |||||
| その他収入: KintoneRecordField.Number; | |||||
| 住所_手入力: KintoneRecordField.SingleLineText; | |||||
| 担当: KintoneRecordField.SingleLineText; | |||||
| 内税: KintoneRecordField.Number; | |||||
| 定期_駐車場名: KintoneRecordField.SingleLineText; | |||||
| 契約金額: KintoneRecordField.Number; | |||||
| 利用者へ表示するプラン名: KintoneRecordField.SingleLineText; | |||||
| 税率: KintoneRecordField.Number; | |||||
| 種別: KintoneRecordField.Dropdown; | |||||
| 住所_使用: KintoneRecordField.SingleLineText; | |||||
| 駐車場備考: KintoneRecordField.Dropdown; | |||||
| 表示順: KintoneRecordField.Number; | |||||
| プラン: KintoneRecordField.Dropdown; | |||||
| チェーンゲート保証金: KintoneRecordField.Number; | |||||
| 年額: KintoneRecordField.Calc; | |||||
| 保証金合計額: KintoneRecordField.Calc; | |||||
| 送付物: KintoneRecordField.CheckBox; | |||||
| プラン変更申請にて変更可能なプラン一覧: { | |||||
| type: "SUBTABLE"; | |||||
| value: { | |||||
| id: string; | |||||
| value: { | |||||
| プラン変更申請にて変更可能なプラン一覧_定期_駐車場名_月額金額_駐車場備考_プラン_種別_支払パターン: KintoneRecordField.SingleLineText; | |||||
| }; | |||||
| }[]; | |||||
| }; | |||||
| }; | |||||
| @@ -0,0 +1,39 @@ | |||||
| import { KintoneRecordField } from "@kintone/rest-api-client"; | |||||
| import { AppRecord } from "."; | |||||
| const F = { | |||||
| プラン名: "定期駐車場プラン", | |||||
| 自動承認グループ名: "自動承認グループ名", | |||||
| 対象車室番号: "対象車室番号", | |||||
| } as const; | |||||
| // export const 支払種別Dropdown = { | |||||
| // 定期料金: "定期料金", | |||||
| // 保証金: "保証金", | |||||
| // 証明書郵送代: "証明書郵送代", | |||||
| // 事務手数料: "事務手数料", | |||||
| // 延滞金: "延滞金", | |||||
| // 余剰金: "余剰金", | |||||
| // } as const; | |||||
| // export type 支払種別Dropdown = | |||||
| // (typeof 支払種別Dropdown)[keyof typeof 支払種別Dropdown]; | |||||
| export const 自動承認グループフィールド名 = F; | |||||
| export type 対象車室番号行データ = { | |||||
| 割当順: KintoneRecordField.Number; | |||||
| 車室番号: KintoneRecordField.SingleLineText; | |||||
| 利用中: KintoneRecordField.CheckBox; | |||||
| 自動承認スキップ: KintoneRecordField.CheckBox; | |||||
| }; | |||||
| export type 自動承認グループ = AppRecord & { | |||||
| [F.プラン名]: KintoneRecordField.SingleLineText; | |||||
| [F.自動承認グループ名]: KintoneRecordField.SingleLineText; | |||||
| [F.対象車室番号]: { | |||||
| type: "SUBTABLE"; | |||||
| value: { | |||||
| id: string; | |||||
| value: 対象車室番号行データ; | |||||
| }[]; | |||||
| }; | |||||
| }; | |||||
| @@ -2,9 +2,14 @@ import { KintoneRecordField } from "@kintone/rest-api-client"; | |||||
| import { AppRecord } from "."; | import { AppRecord } from "."; | ||||
| const F = { | const F = { | ||||
| 契約日: "契約日", | |||||
| 解約日: "解約日", | 解約日: "解約日", | ||||
| 車両番号: "車両番号", | 車両番号: "車両番号", | ||||
| 防犯登録番号: "防犯登録番号", | 防犯登録番号: "防犯登録番号", | ||||
| 定期駐車場名: "定期駐車場名", | |||||
| 顧客コード: "顧客コード", | |||||
| 車室番号: "車室番号", | |||||
| プラン名: "契約駐車場_0", | |||||
| } as const; | } as const; | ||||
| // export const 支払種別Dropdown = { | // export const 支払種別Dropdown = { | ||||
| @@ -22,14 +27,14 @@ export const 車室契約情報フィールド名 = F; | |||||
| export type 車室契約情報 = AppRecord & { | export type 車室契約情報 = AppRecord & { | ||||
| 定期券番号_0: KintoneRecordField.SingleLineText; | 定期券番号_0: KintoneRecordField.SingleLineText; | ||||
| 契約駐車場_0: KintoneRecordField.SingleLineText; | |||||
| [F.プラン名]: KintoneRecordField.SingleLineText; | |||||
| [F.防犯登録番号]: KintoneRecordField.SingleLineText; | [F.防犯登録番号]: KintoneRecordField.SingleLineText; | ||||
| 定額_3月: KintoneRecordField.Number; | 定額_3月: KintoneRecordField.Number; | ||||
| 入金日: KintoneRecordField.Date; | 入金日: KintoneRecordField.Date; | ||||
| 定期駐車場名: KintoneRecordField.SingleLineText; | |||||
| [F.定期駐車場名]: KintoneRecordField.SingleLineText; | |||||
| 担当: KintoneRecordField.SingleLineText; | 担当: KintoneRecordField.SingleLineText; | ||||
| 車室番号: KintoneRecordField.SingleLineText; | |||||
| 契約日: KintoneRecordField.Date; | |||||
| [F.車室番号]: KintoneRecordField.SingleLineText; | |||||
| [F.契約日]: KintoneRecordField.Date; | |||||
| 定額_5月: KintoneRecordField.Number; | 定額_5月: KintoneRecordField.Number; | ||||
| 契約金額: KintoneRecordField.Number; | 契約金額: KintoneRecordField.Number; | ||||
| 障がい者手帳有効期限: KintoneRecordField.Date; | 障がい者手帳有効期限: KintoneRecordField.Date; | ||||
| @@ -37,7 +42,7 @@ export type 車室契約情報 = AppRecord & { | |||||
| 定額_4月: KintoneRecordField.Number; | 定額_4月: KintoneRecordField.Number; | ||||
| 駐車場備考: KintoneRecordField.SingleLineText; | 駐車場備考: KintoneRecordField.SingleLineText; | ||||
| 障がい者手帳画像更新日時: KintoneRecordField.DateTime; | 障がい者手帳画像更新日時: KintoneRecordField.DateTime; | ||||
| 顧客コード: KintoneRecordField.Number; | |||||
| [F.顧客コード]: KintoneRecordField.Number; | |||||
| 解約減額: KintoneRecordField.Number; | 解約減額: KintoneRecordField.Number; | ||||
| 顧客名カナ_マスタ: KintoneRecordField.SingleLineText; | 顧客名カナ_マスタ: KintoneRecordField.SingleLineText; | ||||
| 定額_6月: KintoneRecordField.Number; | 定額_6月: KintoneRecordField.Number; | ||||
| @@ -0,0 +1,34 @@ | |||||
| import { KintoneRecordField } from "@kintone/rest-api-client"; | |||||
| import { AppRecord } from "."; | |||||
| const F = { | |||||
| 駐車場名: "定期駐車場", | |||||
| 車室番号: "車室番号", | |||||
| 状態: "状態", | |||||
| 契約レコード番号: "契約情報", | |||||
| } as const; | |||||
| export const 状態Dropdown = { | |||||
| 空き: "空き", | |||||
| 契約中: "契約中", | |||||
| } as const; | |||||
| export type 状態Dropdown = (typeof 状態Dropdown)[keyof typeof 状態Dropdown]; | |||||
| export const 車室情報2フィールド名 = F; | |||||
| export type 車室情報2 = AppRecord & { | |||||
| 契約開始日: KintoneRecordField.Date; | |||||
| [F.契約レコード番号]: KintoneRecordField.Number; | |||||
| メモ: KintoneRecordField.MultiLineText; | |||||
| [F.車室番号]: KintoneRecordField.SingleLineText; | |||||
| 定期駐車場プラン: KintoneRecordField.SingleLineText; | |||||
| 車室タイプ: KintoneRecordField.Dropdown; | |||||
| 顧客名: KintoneRecordField.SingleLineText; | |||||
| 顧客名カナ: KintoneRecordField.SingleLineText; | |||||
| 定期券番号: KintoneRecordField.SingleLineText; | |||||
| [F.状態]: KintoneRecordField.Dropdown; | |||||
| 契約終了日: KintoneRecordField.Date; | |||||
| 定期駐車場: KintoneRecordField.SingleLineText; | |||||
| 契約駐車場プラン: KintoneRecordField.SingleLineText; | |||||
| 自動承認: KintoneRecordField.CheckBox; | |||||
| }; | |||||
| @@ -16,6 +16,9 @@ const F = { | |||||
| 契約者_郵便番号: "契約者_郵便番号", | 契約者_郵便番号: "契約者_郵便番号", | ||||
| 住所: "住所", | 住所: "住所", | ||||
| 電話番号: "電話番号", | 電話番号: "電話番号", | ||||
| メールアドレス: "メールアドレス", | |||||
| SMBC契約番号: "ContractNo", | |||||
| 支払方法: "支払方法", | |||||
| } as const; | } as const; | ||||
| // export const 支払種別Dropdown = { | // export const 支払種別Dropdown = { | ||||
| @@ -40,7 +43,7 @@ export type 顧客マスタ = AppRecord & { | |||||
| ChargedBranchCode: KintoneRecordField.SingleLineText; | ChargedBranchCode: KintoneRecordField.SingleLineText; | ||||
| ChargedBranchName: KintoneRecordField.SingleLineText; | ChargedBranchName: KintoneRecordField.SingleLineText; | ||||
| [F.引落預金種別]: KintoneRecordField.Number; | [F.引落預金種別]: KintoneRecordField.Number; | ||||
| ContractNo: KintoneRecordField.SingleLineText; | |||||
| [F.SMBC契約番号]: KintoneRecordField.SingleLineText; | |||||
| [F.顧客コード]: KintoneRecordField.Number; | [F.顧客コード]: KintoneRecordField.Number; | ||||
| [F.顧客名]: KintoneRecordField.SingleLineText; | [F.顧客名]: KintoneRecordField.SingleLineText; | ||||
| SMBC口座名義_1: KintoneRecordField.SingleLineText; | SMBC口座名義_1: KintoneRecordField.SingleLineText; | ||||
| @@ -50,7 +53,7 @@ export type 顧客マスタ = AppRecord & { | |||||
| [F.ゆうちょ口座番号]: KintoneRecordField.Number; | [F.ゆうちょ口座番号]: KintoneRecordField.Number; | ||||
| クレジット入金額: KintoneRecordField.Number; | クレジット入金額: KintoneRecordField.Number; | ||||
| コンビニ払入金額: KintoneRecordField.Number; | コンビニ払入金額: KintoneRecordField.Number; | ||||
| メールアドレス: KintoneRecordField.Link; | |||||
| [F.メールアドレス]: KintoneRecordField.Link; | |||||
| ゆうちょ口座名義_0: KintoneRecordField.SingleLineText; | ゆうちょ口座名義_0: KintoneRecordField.SingleLineText; | ||||
| ゆうちょ口座名義_1: KintoneRecordField.SingleLineText; | ゆうちょ口座名義_1: KintoneRecordField.SingleLineText; | ||||
| ゆうちょ口座名義: KintoneRecordField.SingleLineText; | ゆうちょ口座名義: KintoneRecordField.SingleLineText; | ||||
| @@ -60,7 +63,7 @@ export type 顧客マスタ = AppRecord & { | |||||
| [F.顧客名カナ]: KintoneRecordField.SingleLineText; | [F.顧客名カナ]: KintoneRecordField.SingleLineText; | ||||
| 口座振替依頼書: KintoneRecordField.File; | 口座振替依頼書: KintoneRecordField.File; | ||||
| 口座登録催促予定日時: KintoneRecordField.DateTime; | 口座登録催促予定日時: KintoneRecordField.DateTime; | ||||
| 支払方法: KintoneRecordField.SingleLineText; | |||||
| [F.支払方法]: KintoneRecordField.SingleLineText; | |||||
| [F.住所]: KintoneRecordField.SingleLineText; | [F.住所]: KintoneRecordField.SingleLineText; | ||||
| 送付方法: KintoneRecordField.Dropdown; | 送付方法: KintoneRecordField.Dropdown; | ||||
| 台数: KintoneRecordField.Number; | 台数: KintoneRecordField.Number; | ||||
| @@ -70,40 +70,6 @@ module.exports = { | |||||
| // new Dotenv({ systemvars: true }), | // new Dotenv({ systemvars: true }), | ||||
| new ForkTsCheckerWebpackPlugin(), | new ForkTsCheckerWebpackPlugin(), | ||||
| // new BundleAnalyzerPlugin(), | // new BundleAnalyzerPlugin(), | ||||
| { | |||||
| // watchモードのとき再ビルドされたものをアップロードする | |||||
| apply: (compiler) => { | |||||
| compiler.hooks.afterEmit.tapPromise( | |||||
| 'upload javascript files', | |||||
| (compilation) => { | |||||
| if (!compiler.options.watch) return Promise.resolve(); | |||||
| const emittedFiles = Object.keys(compilation.assets) | |||||
| .filter((file) => { | |||||
| const source = compilation.assets[file]; | |||||
| return source.emitted && source.existsAt; | |||||
| }) | |||||
| .map((file) => file.replace('.js', '')); | |||||
| const processes = glob | |||||
| .sync(`@(${emittedFiles.join('|')})/customize-manifest.json`, { | |||||
| cwd: basePath, | |||||
| }) | |||||
| .map((file) => { | |||||
| console.log('\nuploading... ', file); | |||||
| return exec( | |||||
| `yarn upload ${path.resolve(basePath, file)}`, | |||||
| (err, stdout, stderr) => { | |||||
| if (stdout) process.stdout.write(stdout); | |||||
| if (stderr) process.stderr.write(stderr); | |||||
| } | |||||
| ); | |||||
| }); | |||||
| return Promise.all(processes); | |||||
| } | |||||
| ); | |||||
| }, | |||||
| }, | |||||
| new webpack.DefinePlugin({ | new webpack.DefinePlugin({ | ||||
| 'process.env.BUILD_TIME': JSON.stringify(format(new Date(), 'yyyy-MM-dd HH:mm:ss')), | 'process.env.BUILD_TIME': JSON.stringify(format(new Date(), 'yyyy-MM-dd HH:mm:ss')), | ||||
| }), | }), | ||||
| @@ -1264,6 +1264,11 @@ | |||||
| resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" | resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" | ||||
| integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== | integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== | ||||
| "@types/lodash@^4.14.202": | |||||
| version "4.14.202" | |||||
| resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.202.tgz#f09dbd2fb082d507178b2f2a5c7e74bd72ff98f8" | |||||
| integrity sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ== | |||||
| "@types/mime@*": | "@types/mime@*": | ||||
| version "3.0.4" | version "3.0.4" | ||||
| resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.4.tgz#2198ac274de6017b44d941e00261d5bc6a0e0a45" | resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.4.tgz#2198ac274de6017b44d941e00261d5bc6a0e0a45" | ||||