| @@ -46,10 +46,12 @@ | |||
| }, | |||
| "dependencies": { | |||
| "@kintone/rest-api-client": "^2.0.17", | |||
| "@types/lodash": "^4.14.202", | |||
| "@types/sprintf": "^0.1.2", | |||
| "core-js": "^3.6.4", | |||
| "date-fns": "^2.30.0", | |||
| "kintone-ui-component": "^1.14.0", | |||
| "lodash": "^4.17.21", | |||
| "react": "^18.2.0", | |||
| "react-dom": "^18.2.0", | |||
| "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); | |||
| @@ -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顧客マスタ({ | |||
| 顧客コード: Number(record.顧客コード.value), | |||
| }); | |||
| if (customer === null) throw new Error("顧客不正"); | |||
| // 顧客マスタへの反映 | |||
| await client.record.updateRecord({ | |||
| @@ -141,7 +142,7 @@ const 利用者情報変更申請承認 = async (record: 各種申請) => { | |||
| const customer = await get顧客マスタ({ | |||
| 顧客コード: Number(record.顧客コード.value), | |||
| }); | |||
| if (customer === null) throw new Error("顧客不正"); | |||
| await client.record.updateRecord({ | |||
| app: AppID.顧客マスタ, | |||
| 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.車室契約情報, | |||
| 車室情報2: APP_ID.車室情報2, | |||
| 自動承認グループ: APP_ID.自動承認グループ, | |||
| } as const; | |||
| 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 { | |||
| [fieldCode]: { | |||
| value, | |||
| @@ -8,7 +17,7 @@ export const setFieldValue = (fieldCode: string, value: string | object) => { | |||
| export const makeRecordData = (data: { | |||
| [fieldCode: string]: string | object; | |||
| }) => { | |||
| }): Field => { | |||
| let ret = {}; | |||
| Object.keys(data).forEach((fieldCode) => { | |||
| ret = { | |||
| @@ -7,6 +7,9 @@ export type KintoneConfig = { | |||
| 入金予定結果: number; | |||
| 各種申請: number; | |||
| 車室契約情報: number; | |||
| 車室情報2: number; | |||
| 自動承認グループ: number; | |||
| 定期駐車場プランマスタ: number; | |||
| }; | |||
| }; | |||
| @@ -21,6 +24,9 @@ export const kintoneConfig = (): KintoneConfig => { | |||
| 入金予定結果: 272, | |||
| 各種申請: 294, | |||
| 車室契約情報: 253, | |||
| 車室情報2: 279, | |||
| 自動承認グループ: 286, | |||
| 定期駐車場プランマスタ: 257, | |||
| }, | |||
| }; | |||
| } else { | |||
| @@ -34,6 +40,9 @@ export const kintoneConfig = (): KintoneConfig => { | |||
| 入金予定結果: 272, | |||
| 各種申請: 294, | |||
| 車室契約情報: 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 Swal from "sweetalert2"; | |||
| import Swal, { SweetAlertOptions } from "sweetalert2"; | |||
| export const SuccessDialog = Swal.mixin({ | |||
| icon: "success", | |||
| @@ -12,6 +12,9 @@ export const ErrorDialog = Swal.mixin({ | |||
| icon: "error", | |||
| title: "エラーが発生しました", | |||
| }); | |||
| export const WarningDialog = Swal.mixin({ | |||
| icon: "warning", | |||
| }); | |||
| export const ConfirmDialog = Swal.mixin({ | |||
| icon: "info", | |||
| @@ -20,6 +23,15 @@ export const ConfirmDialog = Swal.mixin({ | |||
| cancelButtonText: "キャンセル", | |||
| }); | |||
| export const ShowConfirmDialog = (param: SweetAlertOptions) => { | |||
| return ConfirmDialog.fire(param).then((result) => { | |||
| if (result.isConfirmed) { | |||
| showLoadingDialog(); | |||
| } | |||
| return result; | |||
| }); | |||
| }; | |||
| export const LoadingDialog = Swal.mixin({ | |||
| title: "実行中...", | |||
| text: "画面を閉じないでください", | |||
| @@ -35,7 +47,7 @@ export const LoadingDialog = Swal.mixin({ | |||
| * 必ずawaitを入れて同期処理にすること | |||
| * @param timer | |||
| */ | |||
| export const showLoadingDialog = async (timer: number = 5000) => { | |||
| export const showLoadingDialog = async (timer: number = 10 * 1000) => { | |||
| LoadingDialog.fire({ | |||
| timer, | |||
| }).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 { 車室契約情報 } from "@/types/車室契約情報"; | |||
| import { formatDateStr, now } from "@/common/datetime"; | |||
| import { 車室契約情報, 車室契約情報フィールド名 } from "@/types/車室契約情報"; | |||
| import { KintoneRestAPIClient } from "@kintone/rest-api-client"; | |||
| import { QueryBuilder } from "./query"; | |||
| const client = new KintoneRestAPIClient(); | |||
| @@ -14,3 +16,34 @@ export const get車室契約情報 = async ( | |||
| 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 { フィールド名 } from "@/types"; | |||
| import { 顧客マスタ, 顧客マスタフィールド名 } from "@/types/顧客マスタ"; | |||
| import { KintoneRestAPIClient } from "@kintone/rest-api-client"; | |||
| import { sprintf } from "sprintf"; | |||
| import { QueryBuilder } from "./query"; | |||
| const client = new KintoneRestAPIClient(); | |||
| type Props = { | |||
| レコード番号?: number; | |||
| 顧客コード?: number; | |||
| メールアドレス?: string; | |||
| 電話番号?: string; | |||
| 必須?: boolean; | |||
| }; | |||
| 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 (!!顧客コード) { | |||
| 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( | |||
| 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"; | |||
| export const フィールド名 = { | |||
| レコード番号: "$id", | |||
| } as const; | |||
| const F = フィールド名; | |||
| export type AppRecord = { | |||
| $id: KintoneRecordField.ID; | |||
| [F.レコード番号]: KintoneRecordField.ID; | |||
| $revision: KintoneRecordField.Revision; | |||
| 作成者: KintoneRecordField.Creator; | |||
| レコード番号: KintoneRecordField.RecordNumber; | |||
| @@ -2,9 +2,15 @@ import { KintoneRecordField } from "@kintone/rest-api-client"; | |||
| import { AppRecord } from "."; | |||
| const F = { | |||
| 車室契約情報レコード番号: "contract_record_number", | |||
| 支払対象_利用_年: "target_year", | |||
| 支払対象_利用_月: "target_month", | |||
| 支払対象_利用_月間数: "target_term_month", | |||
| 支払予定日: "payment_plan_date", | |||
| 支払予定金額: "payment_plan_amount", | |||
| 入金予定コード: "payment_plan_code", | |||
| 入金日: "appropriation_date", | |||
| 入金額: "appropriation_amount", | |||
| 支払予定金額: "payment_plan_amount", | |||
| 残金: "remaining_amount", | |||
| 初回振り込み関連申込レコード番号: "first_payment_entry_record_no", | |||
| } as const; | |||
| @@ -23,18 +29,18 @@ export type 支払種別Dropdown = | |||
| export const 入金予定結果フィールド名 = F; | |||
| 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.Date; | |||
| target_year: KintoneRecordField.SingleLineText; | |||
| target_month: KintoneRecordField.SingleLineText; | |||
| [F.支払対象_利用_年]: KintoneRecordField.SingleLineText; | |||
| [F.支払対象_利用_月]: KintoneRecordField.SingleLineText; | |||
| [F.入金額]: KintoneRecordField.Number; | |||
| payment_type: KintoneRecordField.Dropdown; | |||
| customer_name_kana: KintoneRecordField.SingleLineText; | |||
| [F.支払予定金額]: KintoneRecordField.Number; | |||
| target_term_month: KintoneRecordField.SingleLineText; | |||
| [F.支払対象_利用_月間数]: KintoneRecordField.SingleLineText; | |||
| customer_name: KintoneRecordField.SingleLineText; | |||
| parking_name: KintoneRecordField.SingleLineText; | |||
| customer_code: KintoneRecordField.Number; | |||
| @@ -3,6 +3,8 @@ import { AppRecord } from "."; | |||
| const F = { | |||
| 状態: "status", | |||
| 自動承認ステータス: "auto_confirm_status", | |||
| 利用開始希望日: "利用開始希望日", | |||
| } as const; | |||
| export const 状態Dropdown = { | |||
| @@ -18,6 +20,13 @@ export const 状態Dropdown = { | |||
| } as const; | |||
| 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 type 定期申込予約 = AppRecord & { | |||
| @@ -54,6 +63,6 @@ export type 定期申込予約 = AppRecord & { | |||
| ParkingNaviプラン: KintoneRecordField.SingleLineText; | |||
| 日割り分_月: KintoneRecordField.Number; | |||
| 支払方法: KintoneRecordField.Dropdown; | |||
| auto_confirm_status: KintoneRecordField.SingleLineText; | |||
| [F.自動承認ステータス]: KintoneRecordField.SingleLineText; | |||
| [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 "."; | |||
| const F = { | |||
| 契約日: "契約日", | |||
| 解約日: "解約日", | |||
| 車両番号: "車両番号", | |||
| 防犯登録番号: "防犯登録番号", | |||
| 定期駐車場名: "定期駐車場名", | |||
| 顧客コード: "顧客コード", | |||
| 車室番号: "車室番号", | |||
| プラン名: "契約駐車場_0", | |||
| } as const; | |||
| // export const 支払種別Dropdown = { | |||
| @@ -22,14 +27,14 @@ export const 車室契約情報フィールド名 = F; | |||
| export type 車室契約情報 = AppRecord & { | |||
| 定期券番号_0: KintoneRecordField.SingleLineText; | |||
| 契約駐車場_0: KintoneRecordField.SingleLineText; | |||
| [F.プラン名]: KintoneRecordField.SingleLineText; | |||
| [F.防犯登録番号]: KintoneRecordField.SingleLineText; | |||
| 定額_3月: KintoneRecordField.Number; | |||
| 入金日: KintoneRecordField.Date; | |||
| 定期駐車場名: KintoneRecordField.SingleLineText; | |||
| [F.定期駐車場名]: KintoneRecordField.SingleLineText; | |||
| 担当: KintoneRecordField.SingleLineText; | |||
| 車室番号: KintoneRecordField.SingleLineText; | |||
| 契約日: KintoneRecordField.Date; | |||
| [F.車室番号]: KintoneRecordField.SingleLineText; | |||
| [F.契約日]: KintoneRecordField.Date; | |||
| 定額_5月: KintoneRecordField.Number; | |||
| 契約金額: KintoneRecordField.Number; | |||
| 障がい者手帳有効期限: KintoneRecordField.Date; | |||
| @@ -37,7 +42,7 @@ export type 車室契約情報 = AppRecord & { | |||
| 定額_4月: KintoneRecordField.Number; | |||
| 駐車場備考: KintoneRecordField.SingleLineText; | |||
| 障がい者手帳画像更新日時: KintoneRecordField.DateTime; | |||
| 顧客コード: KintoneRecordField.Number; | |||
| [F.顧客コード]: KintoneRecordField.Number; | |||
| 解約減額: KintoneRecordField.Number; | |||
| 顧客名カナ_マスタ: KintoneRecordField.SingleLineText; | |||
| 定額_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; | |||
| // export const 支払種別Dropdown = { | |||
| @@ -40,7 +43,7 @@ export type 顧客マスタ = AppRecord & { | |||
| ChargedBranchCode: KintoneRecordField.SingleLineText; | |||
| ChargedBranchName: KintoneRecordField.SingleLineText; | |||
| [F.引落預金種別]: KintoneRecordField.Number; | |||
| ContractNo: KintoneRecordField.SingleLineText; | |||
| [F.SMBC契約番号]: KintoneRecordField.SingleLineText; | |||
| [F.顧客コード]: KintoneRecordField.Number; | |||
| [F.顧客名]: KintoneRecordField.SingleLineText; | |||
| SMBC口座名義_1: KintoneRecordField.SingleLineText; | |||
| @@ -50,7 +53,7 @@ export type 顧客マスタ = AppRecord & { | |||
| [F.ゆうちょ口座番号]: KintoneRecordField.Number; | |||
| クレジット入金額: KintoneRecordField.Number; | |||
| コンビニ払入金額: KintoneRecordField.Number; | |||
| メールアドレス: KintoneRecordField.Link; | |||
| [F.メールアドレス]: KintoneRecordField.Link; | |||
| ゆうちょ口座名義_0: KintoneRecordField.SingleLineText; | |||
| ゆうちょ口座名義_1: KintoneRecordField.SingleLineText; | |||
| ゆうちょ口座名義: KintoneRecordField.SingleLineText; | |||
| @@ -60,7 +63,7 @@ export type 顧客マスタ = AppRecord & { | |||
| [F.顧客名カナ]: KintoneRecordField.SingleLineText; | |||
| 口座振替依頼書: KintoneRecordField.File; | |||
| 口座登録催促予定日時: KintoneRecordField.DateTime; | |||
| 支払方法: KintoneRecordField.SingleLineText; | |||
| [F.支払方法]: KintoneRecordField.SingleLineText; | |||
| [F.住所]: KintoneRecordField.SingleLineText; | |||
| 送付方法: KintoneRecordField.Dropdown; | |||
| 台数: KintoneRecordField.Number; | |||
| @@ -70,40 +70,6 @@ module.exports = { | |||
| // new Dotenv({ systemvars: true }), | |||
| new ForkTsCheckerWebpackPlugin(), | |||
| // 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({ | |||
| '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" | |||
| 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@*": | |||
| version "3.0.4" | |||
| resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.4.tgz#2198ac274de6017b44d941e00261d5bc6a0e0a45" | |||