{ "HeaderInfo": { "AssemblyVersion": "1.5.6.1", "BaseSiteId": 504317, "Server": "https://nextoffice.next-hd.co.jp/pleasanter", "CreatorName": "野木 健一郎", "PackageTime": "2026-08-31T16:55:28.9166354+09:00", "Convertors": [ { "SiteId": 504317, "SiteTitle": "【デモ版】新版積算問合せ", "ReferenceType": "Sites", "IncludeData": false, "Order": "[504321,504322,504319,504320,504318]" }, { "SiteId": 504318, "SiteTitle": "テンプレート", "ReferenceType": "Sites", "IncludeData": false, "Order": "[]" }, { "SiteId": 504319, "SiteTitle": "問い合わせ不要理由テンプレ管理", "ReferenceType": "Results", "IncludeData": false }, { "SiteId": 504320, "SiteTitle": "遅延理由テンプレ管理", "ReferenceType": "Results", "IncludeData": false }, { "SiteId": 504321, "SiteTitle": "【デモ版】①物件基本情報", "ReferenceType": "Results", "IncludeData": false }, { "SiteId": 504322, "SiteTitle": "【デモ版】②問い合わせ内容管理", "ReferenceType": "Results", "IncludeData": false } ], "IncludeSitePermission": true, "IncludeRecordPermission": true, "IncludeColumnPermission": true, "IncludeNotifications": true, "IncludeReminders": true }, "Sites": [ { "TenantId": 1, "SiteId": 504317, "Title": "【デモ版】新版積算問合せ", "SiteName": "", "SiteGroupName": "", "Body": "", "GridGuide": "", "EditorGuide": "", "CalendarGuide": "", "CrosstabGuide": "", "GanttGuide": "", "BurnDownGuide": "", "TimeSeriesGuide": "", "AnalyGuide": "", "KambanGuide": "", "ImageLibGuide": "", "ReferenceType": "Sites", "ParentId": 74663, "InheritPermission": 504317, "SiteSettings": { "Version": 1.017, "ReferenceType": "Sites", "NoDisplayIfReadOnly": false, "NotInheritPermissionsWhenCreatingSite": false }, "Publish": false, "DisableCrossSearch": false, "Comments": [] }, { "TenantId": 1, "SiteId": 504318, "Title": "テンプレート", "SiteName": "", "SiteGroupName": "", "Body": "", "GridGuide": "", "EditorGuide": "", "CalendarGuide": "", "CrosstabGuide": "", "GanttGuide": "", "BurnDownGuide": "", "TimeSeriesGuide": "", "AnalyGuide": "", "KambanGuide": "", "ImageLibGuide": "", "ReferenceType": "Sites", "ParentId": 504317, "InheritPermission": 504318, "SiteSettings": { "Version": 1.017, "ReferenceType": "Sites", "NoDisplayIfReadOnly": false, "NotInheritPermissionsWhenCreatingSite": false }, "Publish": false, "DisableCrossSearch": false, "Comments": [] }, { "TenantId": 1, "SiteId": 504319, "Title": "問い合わせ不要理由テンプレ管理", "SiteName": "", "SiteGroupName": "", "Body": "", "GridGuide": "", "EditorGuide": "", "CalendarGuide": "", "CrosstabGuide": "", "GanttGuide": "", "BurnDownGuide": "", "TimeSeriesGuide": "", "AnalyGuide": "", "KambanGuide": "", "ImageLibGuide": "", "ReferenceType": "Results", "ParentId": 504318, "InheritPermission": 504319, "SiteSettings": { "Version": 1.017, "ReferenceType": "Results", "GridColumns": [ "ResultId", "Status", "NumA", "ClassA", "DescriptionA", "Comments", "Updator", "UpdatedTime" ], "EditorColumnHash": { "General": [ "Title", "NumA", "ClassA", "DescriptionA", "Comments" ] }, "TitleColumns": [ "ClassA" ], "Columns": [ { "ColumnName": "ClassA", "LabelText": "不要理由", "FieldCss": "field-wide" }, { "ColumnName": "DescriptionA", "LabelText": "内容" }, { "ColumnName": "NumA", "LabelText": "ソート用" } ], "NoDisplayIfReadOnly": false, "NotInheritPermissionsWhenCreatingSite": false }, "Publish": false, "DisableCrossSearch": false, "Comments": [] }, { "TenantId": 1, "SiteId": 504320, "Title": "遅延理由テンプレ管理", "SiteName": "", "SiteGroupName": "", "Body": "", "GridGuide": "", "EditorGuide": "", "CalendarGuide": "", "CrosstabGuide": "", "GanttGuide": "", "BurnDownGuide": "", "TimeSeriesGuide": "", "AnalyGuide": "", "KambanGuide": "", "ImageLibGuide": "", "ReferenceType": "Results", "ParentId": 504318, "InheritPermission": 504320, "SiteSettings": { "Version": 1.017, "ReferenceType": "Results", "GridColumns": [ "ResultId", "Status", "NumA", "ClassA", "DescriptionA", "Comments", "Updator", "UpdatedTime" ], "EditorColumnHash": { "General": [ "ResultId", "Ver", "Title", "Status", "NumA", "ClassA", "DescriptionA", "Comments" ] }, "Columns": [ { "ColumnName": "ClassA", "LabelText": "遅延理由", "ChoicesText": "0,外部見積り待ち\n1,施工検討中\n2,会社相談中\n3,積算問合わせ集中のため\n4,依頼者質疑回答待ち", "SearchType": "PartialMatch" }, { "ColumnName": "DescriptionA", "LabelText": "内容" }, { "ColumnName": "NumA", "LabelText": "ソート用" } ], "NoDisplayIfReadOnly": false, "NotInheritPermissionsWhenCreatingSite": false }, "Publish": false, "DisableCrossSearch": false, "Comments": [] }, { "TenantId": 1, "SiteId": 504321, "Title": "【デモ版】①物件基本情報", "SiteName": "", "SiteGroupName": "", "Body": "・2026.3.10作成", "GridGuide": "新規物件は、一覧画面の右上「+新規作成」ボタンから登録してください。\n見積依頼は「新規見積依頼」ボタンから依頼を進めてください。\n\n■LINEWORKS:[営業積算相談窓口](https://line.worksmobile.com/message/send?userNoList=800300000001353&version=25&type=counselor) ※窓口の対応内容や対応時間の確認は[こちら](https://board.worksmobile.com/main/article/4080000000785782853?t=41276&boardNo=my&isShowFilesArea=false)\n■LINEWORKS掲示板:[営業積算関連情報ポータル](https://board.worksmobile.com/main/article/4080000000813091905?t=70969&boardNo=my&isShowFilesArea=false)", "EditorGuide": "新規物件は、一覧画面の右上「+新規作成」ボタンから登録してください。\n見積依頼は「新規見積依頼」ボタンから依頼を進めてください。\n\n■LINEWORKS:[営業積算相談窓口](https://line.worksmobile.com/message/send?userNoList=800300000001353&version=25&type=counselor) ※窓口の対応内容や対応時間の確認は[こちら](https://board.worksmobile.com/main/article/4080000000785782853?t=41276&boardNo=my&isShowFilesArea=false)\n■LINEWORKS掲示板:[営業積算関連情報ポータル](https://board.worksmobile.com/main/article/4080000000813091905?t=70969&boardNo=my&isShowFilesArea=false)", "CalendarGuide": "", "CrosstabGuide": "", "GanttGuide": "", "BurnDownGuide": "", "TimeSeriesGuide": "", "AnalyGuide": "", "KambanGuide": "", "ImageLibGuide": "", "ReferenceType": "Results", "ParentId": 504317, "InheritPermission": 504321, "SiteSettings": { "Version": 1.017, "ReferenceType": "Results", "GridColumns": [ "ResultId", "ClassA", "ClassS", "ClassB", "Class001", "Class021", "Class022", "Class023", "Class040", "UpdatedTime" ], "FilterColumns": [ "Status", "ClassB", "Class022", "Class031", "Class032", "Class033", "Class034", "Class035", "Class036", "Class037" ], "EditorColumnHash": { "General": [ "ResultId", "Ver", "Title", "Comments", "ClassA", "ClassB", "Status", "ClassF", "_Section-1", "ClassY", "ClassZ", "ClassS", "_Section-2", "Class001", "Class002", "Class003", "Class004", "_Section-7", "Class005", "Class006", "Class007", "Class008", "_Section-8", "Class009", "Class010", "Class011", "Class012", "Class015", "_Section-9", "Class021", "Class022", "Class023", "Class024", "Class025", "ClassM", "ClassN", "_Section-4", "Date001", "Date002", "_Section-3", "Class031", "Class032", "Class033", "Class034", "Class035", "Class036", "Class037", "Class038", "Class151", "_Section-6", "Class061", "Class062", "Class063", "Class064", "Class152", "Class153", "Class154", "Class199", "Class200", "_Links-504322" ] }, "GeneralTabLabelText": "物件情報", "TabLatestId": 1, "SectionLatestId": 9, "Sections": [ { "Id": 1, "LabelText": "", "AllowExpand": false, "Expand": true }, { "Id": 2, "LabelText": "物件情報", "AllowExpand": false, "Expand": true }, { "Id": 7, "LabelText": "", "AllowExpand": false, "Expand": true }, { "Id": 8, "LabelText": "", "AllowExpand": false, "Expand": true }, { "Id": 9, "LabelText": "", "AllowExpand": false, "Expand": true }, { "Id": 4, "LabelText": "スケジュール ※商談中の場合は、仮予定日を選択してください(後から変更可)", "AllowExpand": false, "Expand": true }, { "Id": 3, "LabelText": "物件担当者", "AllowExpand": false, "Expand": true }, { "Id": 6, "LabelText": "CCで送ってほしい社員・パートがいる場合は、名前を検索・選択してください", "AllowExpand": false, "Expand": true } ], "TitleColumns": [ "ClassA", "Class022", "Class023" ], "LinkColumns": [ "ResultId", "Title", "ClassA", "ClassB", "ClassK", "ClassS", "ClassY", "ClassZ", "Class021", "Class022", "Class023", "Class031", "Class032" ], "Columns": [ { "ColumnName": "Comments", "LabelText": "変更履歴", "AllowImage": false }, { "ColumnName": "Status", "LabelText": "登録状況", "ChoicesText": "100,新規登録,新規,new-status-white\n200,登録完了,登録,new-status-pink\n900,依頼終了,依頼,new-status-blue\n910,保留,保留,new-status-grey\n920,取消,取消,new-status-grey", "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "ClassA", "LabelText": "管理番号", "NoWrap": true, "AutoNumberingFormat": "[yy][nnnn][ClassM][ClassN]", "AutoNumberingResetType": "Year", "ExtendedFieldCss": "code-readonly2", "ExtendedHtmlAfterControl": "
\n※自動採番\n
" }, { "ColumnName": "ClassB", "LabelText": "登録者", "ChoicesText": "[[Users*]]", "UseSearch": true, "DefaultInput": "[[Self]]", "ExtendedFieldCss": "code-readonly2", "SearchType": "PartialMatch" }, { "ColumnName": "ClassF", "LabelText": "年", "Hide": true }, { "ColumnName": "ClassZ", "LabelText": "契約コード", "ExtendedFieldCss": "code-readonly2", "CopyByDefault": true }, { "ColumnName": "ClassS", "LabelText": "案件状況", "ChoicesText": "0,未契約,未契約,new-status-light-white\n1,契約済み,契約済み,new-status-green", "NotInsertBlankChoice": true, "DefaultInput": "0", "NoWrap": true, "SearchType": "PartialMatch" }, { "ColumnName": "Class001", "LabelText": "施主1・姓", "GridLabelText": "施主名", "NoWrap": true, "GridDesign": "[Class001][Class002]\n[Class003][Class004]", "ValidateRequired": true }, { "ColumnName": "Class002", "LabelText": "施主1・名", "ValidateRequired": true }, { "ColumnName": "Class003", "LabelText": "施主1・姓(カナ)", "InputGuide": "全角カタカナで入力", "NoWrap": true, "ValidateRequired": true, "ClientRegexValidation": "^[ァ-ヶー0-90-9  ]+$", "RegexValidationMessage": "この項目は全角カナおよび全角数字のみ入力してください。" }, { "ColumnName": "Class004", "LabelText": "施主1・名(カナ)", "InputGuide": "全角カタカナで入力", "ValidateRequired": true, "ClientRegexValidation": "^[ァ-ヶー0-90-9  ]+$", "RegexValidationMessage": "この項目は全角カナおよび全角数字のみ入力してください。" }, { "ColumnName": "Class005", "LabelText": "施主2・姓", "NoWrap": true }, { "ColumnName": "Class006", "LabelText": "施主2・名" }, { "ColumnName": "Class010", "LabelText": "施主3・名" }, { "ColumnName": "Class012", "LabelText": "施主3・名(カナ)", "ClientRegexValidation": "^[ァ-ヶー0-90-9  ]+$" }, { "ColumnName": "ClassM", "LabelText": "エリア記号", "NoWrap": true, "Hide": true }, { "ColumnName": "ClassN", "LabelText": "ブランド記号", "Hide": true }, { "ColumnName": "Date001", "LabelText": "承認図予定日" }, { "ColumnName": "Date002", "LabelText": "着工予定日" }, { "ColumnName": "Class199", "LabelText": "重複許容", "ChoicesText": "重複1\n重複2\n重複3\n重複4\n重複5\n重複6\n重複7\n重複8\n重複9\n重複10" }, { "ColumnName": "Class200", "LabelText": "重複チェック", "Hide": true, "NoDuplication": true, "MessageWhenDuplicated": "本物件はすでに登録されております。同姓同名の別物件の場合は営業積算窓口へご連絡ください", "FieldCss": "field-wide" }, { "ColumnName": "UpdatedTime", "GridFormat": "Ymdhm" }, { "ColumnName": "Class061", "LabelText": "CC①", "ChoicesText": "[[Users*]]", "UseSearch": true, "SearchType": "PartialMatch" }, { "ColumnName": "Class062", "LabelText": "CC②", "ChoicesText": "[[Users*]]", "UseSearch": true, "SearchType": "PartialMatch" }, { "ColumnName": "Class063", "LabelText": "CC③", "ChoicesText": "[[Users*]]", "UseSearch": true, "NoWrap": true, "SearchType": "PartialMatch" }, { "ColumnName": "Class064", "LabelText": "CC④", "ChoicesText": "[[Users*]]", "UseSearch": true, "SearchType": "PartialMatch" }, { "ColumnName": "Class031", "LabelText": "契約営業所", "ChoicesText": "[\n {\n \"SiteId\": 96243,\n \"View\": {\n \"ColumnSorterHash\": {\n \"ResultId\": \"asc\"\n }\n }\n }\n]", "SearchType": "PartialMatch" }, { "ColumnName": "Class032", "LabelText": "主担当営業", "ChoicesText": "[[Users*]]", "UseSearch": true, "NoWrap": true, "SearchType": "PartialMatch" }, { "ColumnName": "Class033", "LabelText": "副担当営業", "ChoicesText": "[[Users*]]", "UseSearch": true, "SearchType": "PartialMatch" }, { "ColumnName": "Class034", "LabelText": "営業設計", "ChoicesText": "[[Users*]]", "UseSearch": true, "NoWrap": true, "SearchType": "PartialMatch" }, { "ColumnName": "Class035", "LabelText": "管理設計", "ChoicesText": "[[Users*]]", "UseSearch": true, "SearchType": "PartialMatch" }, { "ColumnName": "Class036", "LabelText": "担当IC", "ChoicesText": "[[Users*]]", "UseSearch": true, "NoWrap": true, "SearchType": "PartialMatch" }, { "ColumnName": "Class037", "LabelText": "担当監督", "ChoicesText": "[[Users*]]", "UseSearch": true, "SearchType": "PartialMatch" }, { "ColumnName": "Class038", "LabelText": "所属長", "ChoicesText": "[[Users*]]", "UseSearch": true, "NoWrap": true, "SearchType": "PartialMatch" }, { "ColumnName": "Class007", "LabelText": "施主2・姓(カナ)", "NoWrap": true, "ClientRegexValidation": "^[ァ-ヶー0-90-9  ]+$" }, { "ColumnName": "Class008", "LabelText": "施主2・名(カナ)", "ClientRegexValidation": "^[ァ-ヶー0-90-9  ]+$" }, { "ColumnName": "Class009", "LabelText": "施主3・姓", "NoWrap": true }, { "ColumnName": "Class022", "LabelText": "エリア", "ChoicesText": "[\n {\n \"SiteId\": 210699,\n \"View\": {\n \"ColumnSorterHash\": {\n \"ResultId\": \"asc\"\n }\n }\n }\n]", "ValidateRequired": true, "SearchType": "PartialMatch" }, { "ColumnName": "Class011", "LabelText": "施主3・姓(カナ)", "NoWrap": true, "ClientRegexValidation": "^[ァ-ヶー0-90-9  ]+$" }, { "ColumnName": "Class023", "LabelText": "契約ブランド", "ChoicesText": "[\n {\n \"SiteId\": 109100,\n \"View\": {\n \"ColumnSorterHash\": {\n \"ResultId\": \"asc\"\n }\n }\n }\n]", "NoWrap": true, "SearchType": "PartialMatch" }, { "ColumnName": "Class024", "LabelText": "防火指定", "ChoicesText": "無,無,無,status-grey\n準防火,準防火,準防,status-yellow\n準耐火,準耐火,準耐,status-red", "NoWrap": true, "SearchType": "PartialMatch" }, { "ColumnName": "Class025", "LabelText": "建物種類", "ChoicesText": "平屋\n2階建て\n3階建て", "SearchType": "PartialMatch" }, { "ColumnName": "Class021", "LabelText": "建上地", "FieldCss": "field-wide" }, { "ColumnName": "Class040", "GridLabelText": "物件担当者", "GridDesign": "営業:[Class032] 設計:[Class034] \nIC:[Class036] 監督:[Class037]" }, { "ColumnName": "ClassY", "LabelText": "マスターシート", "ChoicesText": "[\n {\n \"SiteId\": 189112,\n \"SearchFormat\": \"[ClassA] - [ClassQ] 様 ([ClassF] [ClassG])\",\n \"View\": {\n \"ColumnSorterHash\": {\n \"ResultId\": \"desc\"\n }\n }\n }\n]", "UseSearch": true, "NoWrap": true, "ExtendedHtmlAfterControl": "
\n※マスターシート登録済み物件は、上記より選択し作成ボタンを押すと登録情報が自動反映されます\n
", "CopyByDefault": true, "FieldCss": "field-wide", "SearchType": "PartialMatch" }, { "ColumnName": "Class015", "LabelText": "施主名マージ", "NoWrap": true, "Hide": true, "FieldCss": "field-wide" }, { "ColumnName": "Class151", "LabelText": "担当者一覧", "ChoicesText": "[[Users*]]", "UseSearch": true, "MultipleSelections": true, "Hide": true, "FieldCss": "field-wide" }, { "ColumnName": "Class152", "LabelText": "CC一覧", "ChoicesText": "[[Users*]]", "UseSearch": true, "MultipleSelections": true, "Hide": true, "FieldCss": "field-wide" }, { "ColumnName": "Class153", "LabelText": "担当者・CC一覧", "ChoicesText": "[[Users*]]", "UseSearch": true, "MultipleSelections": true, "Hide": true, "FieldCss": "field-wide" }, { "ColumnName": "Class154", "LabelText": "依頼者・担当者・CC一覧", "ChoicesText": "[[Users*]]", "UseSearch": true, "MultipleSelections": true, "Hide": true, "FieldCss": "field-wide" } ], "Links": [ { "ColumnName": "ClassY", "SiteId": 189112, "SearchFormat": "[ClassA] - [ClassQ] 様 ([ClassF] [ClassG])", "View": { "Id": 0, "ColumnSorterHash": { "ResultId": "desc" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "JsonFormat": true }, { "ColumnName": "Class022", "SiteId": 210699, "View": { "Id": 0, "ColumnSorterHash": { "ResultId": "asc" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "JsonFormat": true }, { "ColumnName": "Class023", "SiteId": 109100, "View": { "Id": 0, "ColumnSorterHash": { "ResultId": "asc" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "JsonFormat": true }, { "ColumnName": "Class031", "SiteId": 96243, "View": { "Id": 0, "ColumnSorterHash": { "ResultId": "asc" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "JsonFormat": true } ], "Processes": [ { "Id": 1, "Name": "登録完了", "DisplayName": "登録完了", "CurrentStatus": 100, "ChangedStatus": 200, "Description": "実行者:登録者(本人限定)/要入力チェックあり/通知メールあり/確認プロンプトあり", "OnClick": "$p.ex.processScript($(this));", "ValidateInputs": [ { "Id": 1, "ColumnName": "Class001", "Required": true }, { "Id": 2, "ColumnName": "Class002", "Required": true }, { "Id": 3, "ColumnName": "Class003", "Required": true }, { "Id": 4, "ColumnName": "Class004", "Required": true }, { "Id": 5, "ColumnName": "Class021", "Required": true }, { "Id": 6, "ColumnName": "Class022", "Required": true }, { "Id": 7, "ColumnName": "Class023", "Required": true }, { "Id": 8, "ColumnName": "Class031", "Required": true }, { "Id": 9, "ColumnName": "Class032", "Required": true } ], "View": { "Id": 0, "ColumnFilterHash": { "ClassB": "[\"Own\"]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "Notifications": [ { "Type": 1, "Subject": "【デモ版】【営業積算】[ClassA] [Class015]様 : 物件登録完了", "Address": "e-sekisan@next-hd.co.jp", "MediaType": "application/json", "Body": "【デモ版】\n物件情報の登録が完了しました。\n\n内容をご確認ください。\n\n{Url}\n\n----------\n管理番号:[ClassA]\n施主名:[Class001] [Class002]様\n----------\n\n■■■", "BeforeCondition": 0, "AfterCondition": 0, "Expression": 0, "Id": 1 } ] }, { "Id": 2, "Name": "依頼受付終了", "DisplayName": "依頼受付終了", "CurrentStatus": 200, "ChangedStatus": 900, "Description": "実行者:営業積算(Dept25)/要入力チェックなし/通知メールあり/確認プロンプトあり", "OnClick": "$p.ex.processScript($(this));", "Depts": [ 25 ], "View": { "Id": 0, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "Notifications": [ { "Type": 1, "Subject": "【デモ版】【営業積算】[ClassA] [Class015]様 : 依頼受付終了", "Address": "[ClassB]", "CcAddress": "e-sekisan@next-hd.co.jp", "MediaType": "application/json", "Body": "【デモ版】\n営業積算より\n本件について依頼受付を終了しましたのでご連絡します。\n\n下記URLよりご確認ください。\n\n※このメールは送信専用です。\n 本メールに返信いただいても、内容は確認できませんのでご了承ください。\n お問い合わせは、営業積算窓口までご連絡ください。\n\n{Url}\n\n----------\n管理番号:[ClassA]\n施主名:[Class001] [Class002]様\n----------\n\n■■■", "BeforeCondition": 0, "AfterCondition": 0, "Expression": 0, "Id": 1 } ] }, { "Id": 3, "Name": "物件保留", "DisplayName": "物件保留", "CurrentStatus": -1, "ChangedStatus": 910, "Description": "実行者:営業積算(Dept25)/要入力チェックなし/通知メールあり/確認プロンプトあり/どのStatusからでも実行可", "OnClick": "$p.ex.processScript($(this));", "Depts": [ 25 ], "View": { "Id": 0, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "Notifications": [ { "Type": 1, "Subject": "【デモ版】【営業積算】[ClassA] [Class015]様 : 物件保留", "Address": "[ClassB]", "CcAddress": "e-sekisan@next-hd.co.jp", "MediaType": "application/json", "Body": "【デモ版】\n営業積算より\n本件を保留といたしましたのでご連絡します。\n\n下記URLよりご確認ください。\n\n※このメールは送信専用です。\n 本メールに返信いただいても、内容は確認できませんのでご了承ください。\n お問い合わせは、営業積算窓口までご連絡ください。\n\n{Url}\n\n----------\n管理番号:[ClassA]\n施主名:[Class001] [Class002]様\n----------\n\n■■■", "BeforeCondition": 0, "AfterCondition": 0, "Expression": 0, "Id": 1 } ] }, { "Id": 4, "Name": "物件取消", "DisplayName": "物件取消", "CurrentStatus": -1, "ChangedStatus": 920, "Description": "実行者:営業積算(Dept25)/要入力チェックなし/通知メールあり/確認プロンプトあり/どのStatusからでも実行可", "OnClick": "$p.ex.processScript($(this));", "Depts": [ 25 ], "View": { "Id": 0, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "Notifications": [ { "Type": 1, "Subject": "【デモ版】【営業積算】[ClassA] [Class015]様 : 物件取消", "Address": "[ClassB]", "CcAddress": "e-sekisan@next-hd.co.jp", "MediaType": "application/json", "Body": "【デモ版】\n営業積算より\n本件を取消といたしましたのでご連絡します。\n\n下記URLよりご確認ください。\n\n※このメールは送信専用です。\n 本メールに返信いただいても、内容は確認できませんのでご了承ください。\n お問い合わせは、営業積算窓口までご連絡ください。\n\n{Url}\n\n----------\n管理番号:[ClassA]\n施主名:[Class001] [Class002]様\n----------\n\n■■■", "BeforeCondition": 0, "AfterCondition": 0, "Expression": 0, "Id": 1 } ] }, { "Id": 5, "Name": "登録完了へ戻す", "DisplayName": "登録完了へ戻す", "CurrentStatus": -1, "ChangedStatus": 200, "Description": "実行者:営業積算(Dept25)/要入力チェックなし/通知メールあり/確認プロンプトあり", "OnClick": "$p.ex.processScript($(this));", "Depts": [ 25 ], "View": { "Id": 0, "ColumnFilterHash": { "Status": "[\"900\",\"910\",\"920\"]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "Notifications": [ { "Type": 1, "Subject": "【デモ版】【営業積算】[ClassA] [Class015]様 : 登録完了へ再設定", "Address": "[ClassB]", "CcAddress": "e-sekisan@next-hd.co.jp", "MediaType": "application/json", "Body": "【デモ版】\n営業積算より\n保留・取消を解除し、登録完了へ戻しましたのでご連絡します。\n\n下記URLよりご確認ください。\n\n※このメールは送信専用です。\n 本メールに返信いただいても、内容は確認できませんのでご了承ください。\n お問い合わせは、営業積算窓口までご連絡ください。\n\n{Url}\n\n----------\n管理番号:[ClassA]\n施主名:[Class001] [Class002]様\n----------\n\n■■■", "BeforeCondition": 0, "AfterCondition": 0, "Expression": 0, "Id": 1 } ] } ], "StatusControls": [ { "Id": 1, "Name": "登録完了後ロック", "Description": "物件登録完了後、項目欄の入力ができないようにロックをかける", "Status": -1, "ColumnHash": { "Class001": "ReadOnly", "Class002": "ReadOnly", "Class003": "ReadOnly", "Class004": "ReadOnly", "Class022": "ReadOnly" }, "View": { "Id": 0, "ColumnFilterHash": { "Status": "[\"200\",\"900\",\"910\",\"920\"]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 } } ], "Styles": [ { "Title": "01.読み取り専用", "New": true, "Edit": true, "Body": "/*\n@config : next999.json\n@filename : 01_読み取り専用スタイル.css\n@title : 01_読み取り専用スタイル\n@name :\n@siteIds : 335101\n@siteTitles : ①物件基本情報\n@disabled: false\n*/\nlabel.error {\n pointer-events: none;\n z-index: 100;\n border-top: none !important;\n}\n\n.code-readonly {\n pointer-events: none;\n background-color: lightgrey;\n font-weight: bold;\n}\n\n.code-readonly2,\n.code-readonly2+button,\n.code-readonly2+div.ui-icon,\n.code-readonly3,\n.code-readonly3+button,\n.code-readonly3+div.ui-icon {\n font-weight: bold;\n\n &:active {\n pointer-events: none;\n }\n\n a:not(.ui-spinner-button) {\n pointer-events: auto;\n }\n\n}\n\n.code-readonly2 select,\n.code-readonly2 input,\n.code-readonly2 button.ui-multiselect,\n.code-readonly2 .control-markup,\n.code-readonly2 .ui-spinner,\nspan[data-readonly=\"1\"] {\n pointer-events: none;\n\n border: dashed 1px black;\n background-color: lightgray !important;\n color: black !important;\n\n .ui-spinner-input {\n border: none;\n }\n}\n\n.code-readonly3 select,\n.code-readonly3 input,\n.code-readonly3 button.ui-multiselect,\n.code-readonly3 .control-markup,\n.code-readonly3 .ui-spinner {\n pointer-events: none;\n\n border: dashed 1px black;\n\n .ui-spinner-input {\n border: none;\n }\n}\n\n.code-readonly2,\n.code-readonly3,\n.field-normal:has(span[data-readonly=\"1\"]),\n.field-wide:has(span[data-readonly=\"1\"]) {\n position: relative;\n\n &:hover::after {\n content: \"読取り専用です\";\n position: absolute;\n left: 120px;\n top: calc(100% - 9px);\n margin-top: 4px;\n background: #00000080;\n color: #fff;\n padding: 4px 10px;\n border-radius: 4px;\n font-size: 12px;\n font-weight: normal !important;\n pointer-events: none;\n z-index: 9999;\n white-space: nowrap;\n }\n}\n\n.code-required,\nselect[data-validate-required=\"1\"],\ninput[data-validate-required=\"1\"] {\n border: double 3px red !important;\n\n &+button.ui-multiselect {\n border: double 3px red !important;\n }\n\n}\n\n.field-normal:has(.code-required),\n.field-wide:has(.code-required),\n.field-normal:has(select[data-validate-required=\"1\"]),\n.field-wide:has(select[data-validate-required=\"1\"]),\n.field-normal:has(input[data-validate-required=\"1\"]),\n.field-wide:has(input[data-validate-required=\"1\"]) {\n position: relative;\n\n &:hover::after {\n content: \"入力必須です\";\n position: absolute;\n left: 120px;\n top: calc(100% - 9px);\n margin-top: 4px;\n background: #ff000080;\n color: #fff;\n padding: 4px 10px;\n border-radius: 4px;\n font-size: 12px;\n font-weight: normal !important;\n pointer-events: none;\n z-index: 9999;\n white-space: nowrap;\n }\n}\n\n.error {\n border: double 3px red !important;\n}", "Id": 1 }, { "Title": "02.共通", "New": true, "Edit": true, "Body": "/*\n@config : next999.json\n@filename : 02_共通スタイル.css\n@title : 02_共通スタイル\n@name :\n@siteIds : 335101\n@siteTitles : ①物件基本情報\n@disabled: false\n*/\n/*見出しサイズ*/\n.field-section {\n font-size: 1.5em !important;\n font-weight: bold !important;\n height: auto;\n}\n\n/*項目の後ろの行間を少し狭める*/\n.field-normal {\n height: 35px;\n}\n\n.field-wide {\n min-height: 35px;\n padding: 0 10px 5px 0;\n}\n\n/*コメントのある項目の高さだけ少し広げる*/\ndiv:has(.commentAdd).field-normal {\n height: 50px;\n}", "Id": 2 } ], "Scripts": [ { "Title": "01_基本スクリプト.js", "New": true, "Edit": true, "Body": "/*\n@config :\n@filename : ${psFileBasename}\n@title : 01_基本スクリプト\n@name :\n@siteIds :\n@siteTitles : 物件基本情報\n@disabled: false\n*/\n\nlet pageLoading = 0;\n\n//----------------------------------------------------------------------\n//初期処理\nwindow.addEventListener('load', function () {\n if (pageLoading == 0) {\n console.log('Window load Event');\n $p.ex.onLoad();\n }\n});\n\n$p.events.on_editor_load = function () {\n if (pageLoading == 0) {\n console.log('on Editor Load');\n $p.ex.onLoad();\n }\n}\n\n//----------------------------------------------------------------------\n$p.ex.onLoad = function () {\n //ロード開始\n pageLoading = 1;\n\n //初期処理\n $p.ex.init();\n\n}\n\n//初期処理\n$p.ex.init = function () {\n console.log('initialize...');\n\n //ロード時に施主名を予め控えておく\n $p.loadCustomerName();\n\n //依頼発行ボタン名称変更\n $p.changeButtonName();\n\n //登録状況(Status)に応じて依頼発行ボタンの表示・非表示を切り替え\n $p.toggleNewRequestButton();\n\n //ServerScriptが事前取得したエリア・契約ブランド・契約営業所マスタをhiddenから読み込む\n $p.loadStaticMasters();\n\n //保存済みの重複チェックキー(Class200)・重複許容(Class199)を記憶\n //(登録完了後はClass003/004/022がReadOnly化されるため、Class199の変更だけを\n //反映するのに使う。$p.mergeClass200参照)\n $p.rememberDuplicationKeyBaseValues();\n\n //登録完了(Status=200)以降、マスターシートが選択済みの場合のみ選択変更を不可にする\n //(未選択のままなら登録完了後も選択可能にする)\n $p.toggleClassYLock();\n\n //code-readonly2(読取り専用)が設定されている全フィールドをTab移動対象から除外する\n //(ClassYの動的ロックも含め、上記の処理が確定した後に実行する)\n $p.applyReadonlyTabindex();\n\n //新規作成後・登録完了前(Status=100)の既存レコードを開いたとき、登録完了を促すメッセージを表示\n $p.showNewRecordReminder();\n\n //登録完了(Status=200)の状態のとき、②問い合わせ内容管理への新規見積依頼が可能であることを案内\n $p.showRegisteredReminder();\n}\n\n//入力チェック後処理\n$p.events.after_validate = function (args) {\n //担当者一覧のマージ\n $p.mergeUserList();\n}\n\n//画面更新後\n$p.events.after_set_Update = function (args) {\n //初期処理\n $p.ex.init();\n}\n\n//----------------------------------------------------------------------\n//施主名を控える\nlet customerName = {\n 'firstName': '',\n 'lastName': '',\n 'firstNameKana': '',\n 'lastNameKana': ''\n}\n\n//ロード時に施主名を予め控えておく\n$p.loadCustomerName = function () {\n customerName.firstName = $('#Results_Class002').val(); //施主1・名\n customerName.lastName = $('#Results_Class001').val(); //施主1・姓\n customerName.firstNameKana = $('#Results_Class004').val(); //施主1・名(カナ)\n customerName.lastNameKana = $('#Results_Class003').val(); //施主1・姓(カナ)\n}\n\n//----------------------------------------------------------------------\n//入力チェック前処理\n//更新ボタンを押したあと、入力必須項目などのチェックの前に処理される関数\n$p.events.before_validate = function (args) {\n //新規作成時のみ、重複チェックキー(施主氏名・施主氏名カナ・エリア)の最終確認を促す\n //(登録完了処理後は重複チェック自体が働かなくなるため、新規作成の保存前に一度だけ確認する)\n if ($p.action() === 'new') {\n if (!confirm($p.buildNewRecordKeyConfirmMessage())) {\n return false; //保存中断\n }\n }\n\n //施主名がどれか1つでも変更されていたら処理する\n if (customerName.firstName != $('#Results_Class002').val() || customerName.lastName != $('#Results_Class001').val() || customerName.firstNameKana != $('#Results_Class004').val() || customerName.lastNameKana != $('#Results_Class003').val()) {\n $p.mergeCustomerName();\n }\n\n //担当者一覧のマージ\n $p.mergeUserList();\n\n //重複チェック用の連結値をClass200へ保存(Class200はNoDuplication設定済みのため、\n //保存時にPleasanter標準機能が重複判定・アラート表示・保存ブロックを行う)\n $p.mergeClass200();\n}\n\n//----------------------------------------------------------------------\n//重複チェック用に施主1・姓+施主1・名+施主1・姓(カナ)+施主1・名(カナ)+エリア+重複許容を\n//Class200へ連結する\n//主担当営業・契約営業所は人事異動等で変わりうるためキーに含めない(同一物件でも担当者交代で\n//別レコード扱いになってしまうのを防ぐ)。エリアは物件の位置そのもので不変のためキーに採用。\n//エリアが異なれば同姓同名でも別物件として許容する。\n//Class199(重複許容、営業積算専用・通常空欄)は、同一エリアに同姓同名の別物件が実在する\n//稀なケースの回避弁。営業積算が「重複1」~「重複10」のいずれかを設定すると、その値も\n//キーに含まれるため重複チェックをすり抜けられる(同一エリア同姓同名は最大10件まで想定)。\n//\n//Class003/Class004/Class022はStatusControls設定でStatus=200/900/910/920のときReadOnly化される\n//(登録完了後にキー項目を変更不可にするため)。PleasanterのStatusControls ReadOnly適用中は\n//対象項目の.val()が正しい値を返さない既知の挙動があり、そのままここで再連結するとClass200が\n//空/不正な値で上書きされ、重複チェックキーが消えてしまう。登録完了後はキー項目自体が\n//編集不可(=Class003/004/022相当分は変わりようがない)ため、ReadOnly適用中はstr1〜str3の\n//再計算はしない。ただしClass199(重複許容)はReadOnly対象外で登録完了後も営業積算が追加設定\n//する運用のため、Class199の変更だけは既存Class200の末尾を差し替える形で反映する。\n//Class001(姓)・Class002(名)もStatusControls対象外で登録完了後も編集可能だが、重複チェックは\n//新規作成時の一致判定を目的とするため、登録完了後の変更は従来のClass199同様Class200へ反映しない。\n$p.mergeClass200 = function () {\n let status = $('#Results_Status').val();\n let statusLocked = ['200', '900', '910', '920'].includes(status);\n\n if (statusLocked) {\n let newClass199 = $('#Results_Class199').val() || '';\n if (newClass199 === duplicationKeyBaseValues.Class199) return; //重複許容も変更なしなら何もしない\n let base = duplicationKeyBaseValues.Class200;\n if (duplicationKeyBaseValues.Class199 && base.endsWith(duplicationKeyBaseValues.Class199)) {\n base = base.slice(0, base.length - duplicationKeyBaseValues.Class199.length);\n }\n $p.set($('#Results_Class200'), base + newClass199); //重複チェック(重複許容の差し替えのみ)\n return;\n }\n\n let str0a = $p.normalizeForDuplicationKey($('#Results_Class001').val()); //施主1・姓\n let str0b = $p.normalizeForDuplicationKey($('#Results_Class002').val()); //施主1・名\n let str1 = $p.normalizeForDuplicationKey($('#Results_Class003').val()); //施主1・姓(カナ)\n let str2 = $p.normalizeForDuplicationKey($('#Results_Class004').val()); //施主1・名(カナ)\n let str3 = $p.normalizeForDuplicationKey($('#Results_Class022').val()); //エリア\n let str4 = $('#Results_Class199').val() || ''; //重複許容(営業積算専用)\n $p.set($('#Results_Class200'), str0a + str0b + str1 + str2 + str3 + str4); //重複チェック\n}\n\n//----------------------------------------------------------------------\n//重複チェックキー(Class200)へタイムスタンプを付記する\n//「依頼受付終了」「物件取消」実行時に呼ばれる($p.ex.processScript参照)。同一施主・エリアでの\n//新規物件登録がClass200のNoDuplication設定でブロックされないよう、末尾へ_yyyyMMddHHmmssを\n//付加してキーをユニーク化する。「物件保留」は一時的な状態のため対象外(キーは変えず維持する)。\n$p.appendDuplicationKeyTimestamp = function () {\n let current = $('#Results_Class200').val() || '';\n let now = new Date();\n let pad2 = function (n) { return ('0' + n).slice(-2); };\n let timestamp = now.getFullYear() + pad2(now.getMonth() + 1) + pad2(now.getDate()) + pad2(now.getHours()) + pad2(now.getMinutes()) + pad2(now.getSeconds());\n $p.set($('#Results_Class200'), current + '_' + timestamp);\n}\n\n//----------------------------------------------------------------------\n//重複チェックキー(Class200)から付記済みのタイムスタンプを除去する\n//「登録完了へ戻す」実行時に呼ばれる($p.ex.processScript参照)。$p.appendDuplicationKeyTimestampで\n//付加した末尾の_yyyyMMddHHmmssを取り除き、元の重複チェックキーへ戻す。\n$p.removeDuplicationKeyTimestamp = function () {\n let current = $('#Results_Class200').val() || '';\n let stripped = current.replace(/_\\d{14}$/, '');\n if (stripped !== current) {\n $p.set($('#Results_Class200'), stripped);\n }\n}\n\n//----------------------------------------------------------------------\n//保存済みのClass200(重複チェックキー)・Class199(重複許容)をロード時点の値として記憶する\n//(Class200/Class199自体はStatusControlsのReadOnly対象外のため.val()は常に正しく取得できる)\nlet duplicationKeyBaseValues = {\n Class200: '',\n Class199: ''\n};\n\n$p.rememberDuplicationKeyBaseValues = function () {\n duplicationKeyBaseValues.Class200 = $('#Results_Class200').val() || '';\n duplicationKeyBaseValues.Class199 = $('#Results_Class199').val() || '';\n}\n\n//----------------------------------------------------------------------\n//重複チェックキー用の文字列正規化\n//カナ項目はClientRegexValidation(^[ァ-ヶー0-90-9  ]+$)で全角カタカナ・長音・数字・スペース以外\n//入力できない設計だが、半角カナはこの正規表現をすり抜けるため変換する。ひらがな・全角英数字の変換は\n//保険(通常入力では発生しないがAPI経由投入等に備える)。\n$p.normalizeForDuplicationKey = function (str) {\n if (!str) return '';\n let s = String(str);\n\n //半角カナ→全角カナ変換(濁点・半濁点合成)\n s = $p.halfKanaToFullKana(s);\n\n //ひらがな→全角カタカナ変換\n s = s.replace(/[ぁ-ゖ]/g, function (match) {\n return String.fromCharCode(match.charCodeAt(0) + 0x60);\n });\n\n //全角英数字→半角変換\n s = s.replace(/[A-Za-z0-9]/g, function (match) {\n return String.fromCharCode(match.charCodeAt(0) - 0xFEE0);\n });\n\n //半角スペース→全角スペースに統一\n s = s.replace(/ /g, ' ');\n\n //記号除去(氏名区切りとして使われる中黒「・」と長音「ー」は残す)\n s = s.replace(/[!-\\/:-@\\[-`{-~!-/:-@[-`{-~]/g, function (match) {\n return (match === '・') ? match : '';\n });\n\n return s;\n}\n\n//半角カナ文字列を全角カナへ変換する(濁点・半濁点はゼロ幅文字゙゚として後続するため合成する)\n$p.halfKanaToFullKana = function (str) {\n let kanaMap = {\n 'ア': 'ア', 'イ': 'イ', 'ウ': 'ウ', 'エ': 'エ', 'オ': 'オ',\n 'カ': 'カ', 'キ': 'キ', 'ク': 'ク', 'ケ': 'ケ', 'コ': 'コ',\n 'サ': 'サ', 'シ': 'シ', 'ス': 'ス', 'セ': 'セ', 'ソ': 'ソ',\n 'タ': 'タ', 'チ': 'チ', 'ツ': 'ツ', 'テ': 'テ', 'ト': 'ト',\n 'ナ': 'ナ', 'ニ': 'ニ', 'ヌ': 'ヌ', 'ネ': 'ネ', 'ノ': 'ノ',\n 'ハ': 'ハ', 'ヒ': 'ヒ', 'フ': 'フ', 'ヘ': 'ヘ', 'ホ': 'ホ',\n 'マ': 'マ', 'ミ': 'ミ', 'ム': 'ム', 'メ': 'メ', 'モ': 'モ',\n 'ヤ': 'ヤ', 'ユ': 'ユ', 'ヨ': 'ヨ',\n 'ラ': 'ラ', 'リ': 'リ', 'ル': 'ル', 'レ': 'レ', 'ロ': 'ロ',\n 'ワ': 'ワ', 'ヲ': 'ヲ', 'ン': 'ン',\n 'ァ': 'ァ', 'ィ': 'ィ', 'ゥ': 'ゥ', 'ェ': 'ェ', 'ォ': 'ォ',\n 'ッ': 'ッ', 'ャ': 'ャ', 'ュ': 'ュ', 'ョ': 'ョ', 'ー': 'ー'\n };\n let dakutenMap = { 'カ': 'ガ', 'キ': 'ギ', 'ク': 'グ', 'ケ': 'ゲ', 'コ': 'ゴ', 'サ': 'ザ', 'シ': 'ジ', 'ス': 'ズ', 'セ': 'ゼ', 'ソ': 'ゾ', 'タ': 'ダ', 'チ': 'ヂ', 'ツ': 'ヅ', 'テ': 'デ', 'ト': 'ド', 'ハ': 'バ', 'ヒ': 'ビ', 'フ': 'ブ', 'ヘ': 'ベ', 'ホ': 'ボ' };\n let handakutenMap = { 'ハ': 'パ', 'ヒ': 'ピ', 'フ': 'プ', 'ヘ': 'ペ', 'ホ': 'ポ' };\n\n let result = '';\n for (let i = 0; i < str.length; i++) {\n let ch = str[i];\n let next = str[i + 1];\n let full = kanaMap[ch];\n if (full === undefined) {\n result += ch;\n continue;\n }\n if (next === '゙' && dakutenMap[full]) {\n result += dakutenMap[full];\n i++;\n } else if (next === '゚' && handakutenMap[full]) {\n result += handakutenMap[full];\n i++;\n } else {\n result += full;\n }\n }\n return result;\n}\n\n//----------------------------------------------------------------------\n//新規作成時の最終確認メッセージ(重複チェックキーは登録完了後に編集不可になるための警告)\n$p.buildNewRecordKeyConfirmMessage = function () {\n let sei = $('#Results_Class001').val() || '(未入力)';\n let mei = $('#Results_Class002').val() || '(未入力)';\n let seiKana = $('#Results_Class003').val() || '(未入力)';\n let meiKana = $('#Results_Class004').val() || '(未入力)';\n let areaText = $('#Results_Class022 option:selected').text().trim() || '(未選択)';\n return '新規作成します。\\n\\n以下の内容は、登録完了処理後は変更できません。内容に間違いがないか最終確認をお願いします。\\n\\n施主氏名:' + sei + ' ' + mei + '\\n施主氏名(カナ):' + seiKana + ' ' + meiKana + '\\nエリア:' + areaText + '\\n\\nよろしいですか?';\n}\n\n//----------------------------------------------------------------------\n//施主名をマージする\n$p.mergeCustomerName = function () {\n //4つの項目を1つにマージする\n let str1 = $('#Results_Class001').val(); //施主1・姓\n let str2 = $('#Results_Class002').val(); //施主1・名\n let str3 = $('#Results_Class003').val(); //施主1・姓(カナ)\n let str4 = $('#Results_Class004').val(); //施主1・名(カナ)\n //スペースで結合して、施主名(カナ)を作成し、保管\n let mergeName = str1 + ' ' + str2 + '(' + str3 + ' ' + str4 + ')';\n $p.set($('#Results_Class015'), mergeName); //施主名マージ\n}\n\n//----------------------------------------------------------------------\n//ボタン名称変更\n$p.changeButtonName = function () {\n //ボタンの特定(②問い合わせ内容管理への新規作成ボタン)\n let siteId = $p.siteId();\n let button = $('button[data-from-site-id=\"' + siteId + '\"][data-to-site-id=\"504322\"].confirm-unload');\n\n button.each(function () {\n //+アイコンのspanはそのまま残し、末尾のテキストノードだけ書き換える\n let textNode = $(this).contents().filter(function () {\n return this.nodeType === 3; //テキストノードのみ対象\n }).last();\n\n if (textNode.length) {\n textNode[0].nodeValue = '新規見積依頼';\n }\n });\n}\n\n//----------------------------------------------------------------------\n//登録完了(Status=200)以降、マスターシート(ClassY)が選択済みの場合のみ選択変更を不可にする\n//未選択のままなら登録完了後も選択可能(Pleasanter標準のStatusControls ColumnHashは値の有無で\n//条件分岐できないため、こちらでクライアント側から制御する)。\n//フィールドコンテナ(Results_ClassYField)へ既存の読取り専用CSSクラス(code-readonly2)を\n//付け外しする方式(504321の01.読み取り専用スタイルで定義済み、pointer-events:none等を適用)。\n//tabindexの制御は$p.applyReadonlyTabindexに一本化(クラス付与後に呼ばれる想定)。\n$p.toggleClassYLock = function () {\n let status = $('#Results_Status').val();\n let classYVal = $('#Results_ClassY').val();\n let statusLocked = ['200', '900', '910', '920'].includes(status);\n let $classYField = $('#Results_ClassYField');\n\n if (statusLocked && classYVal) {\n $classYField.addClass('code-readonly2');\n } else {\n $classYField.removeClass('code-readonly2');\n }\n}\n\n//----------------------------------------------------------------------\n//code-readonly2(読取り専用)が設定されている全フィールドをTab移動対象から除外する。\n//pointer-events:noneはマウス操作のみ無効化し、Tabキーでのフォーカス移動・キーボード操作での\n//選択変更は防げないため、tabindex=\"-1\"を併用する。静的にExtendedFieldCss: \"code-readonly2\"が\n//設定されている項目(Status/ClassA/ClassB/ClassZ等)と、ClassYのように動的にクラスが\n//付け外しされる項目の両方を、都度まとめて処理する(対象外に戻った要素はtabindexも解除)。\n$p.applyReadonlyTabindex = function () {\n $('select, input, textarea').each(function () {\n let $el = $(this);\n if ($el.closest('.code-readonly2').length) {\n $el.attr('tabindex', '-1');\n } else if ($el.attr('tabindex') === '-1') {\n $el.removeAttr('tabindex');\n }\n });\n}\n\n//----------------------------------------------------------------------\n//新規作成後・登録完了前(Status=100)の既存レコードを開いたとき、登録完了を促すメッセージを表示する\n//新規作成中(保存前、$p.action()==='new')は対象外(保存していないレコードに促す意味がないため)\n$p.showNewRecordReminder = function () {\n if ($p.action() === 'new') return;\n let status = $('#Results_Status').val();\n if (status !== '100') return;\n $p.ex.setMyMessage('new-status-yellow', 'この物件はまだ登録完了していません。見積依頼をしたい場合は「登録完了」ボタンを押してください。');\n}\n\n//----------------------------------------------------------------------\n//登録完了(Status=200)の状態のとき、②問い合わせ内容管理への新規見積依頼が可能であることを案内する\n//(依頼発行ボタン自体はtoggleNewRequestButtonで表示に切り替わるが、気づかれにくいためメッセージでも明示する)\n$p.showRegisteredReminder = function () {\n let status = $('#Results_Status').val();\n if (status !== '200') return;\n $p.ex.setMyMessage('new-status-pink', '登録が完了しています。画面下部の「新規見積依頼」ボタンから②問い合わせ内容管理への見積依頼が可能です。');\n}\n\n//----------------------------------------------------------------------\n//登録状況(Status)が「登録完了(200)」のときだけ依頼発行ボタンを表示、それ以外は非表示にする\n$p.toggleNewRequestButton = function () {\n let siteId = $p.siteId();\n let button = $('button[data-from-site-id=\"' + siteId + '\"][data-to-site-id=\"504322\"].confirm-unload');\n\n let status = $('#Results_Status').val();\n if (status == '200') {\n button.show();\n } else {\n button.hide();\n }\n}\n\n\n$p.mergeUserList = function () {\n //担当者一覧のマージ対象項目(重複除去)\n let users1 = [];\n [\n $('#Results_Class032').val(), //主担当営業\n $('#Results_Class033').val(), //副担当営業\n $('#Results_Class034').val(), //営業設計\n $('#Results_Class035').val(), //管理設計\n $('#Results_Class036').val(), //担当IC\n $('#Results_Class037').val(), //担当監督\n $('#Results_Class038').val(), //所属長\n ].forEach(function (v) {\n if (v && !users1.includes(v)) users1.push(v);\n });\n\n let mergeValue = JSON.stringify(users1); //担当者一覧のマージ対象項目をJSON文字列化\n let class151 = JSON.stringify($('#Results_Class151').val()); //担当者一覧\n\n //前と内容が同じ場合は上書きしない\n if (mergeValue !== class151) {\n $p.set($('#Results_Class151'), mergeValue); //担当者一覧\n }\n\n //CC一覧のマージ対象項目(重複除去)\n let usersCC = [];\n [\n $('#Results_Class061').val(), //CC1\n $('#Results_Class062').val(), //CC2\n $('#Results_Class063').val(), //CC3\n $('#Results_Class064').val(), //CC4\n ].forEach(function (v) {\n if (v && !usersCC.includes(v)) usersCC.push(v);\n });\n\n let mergeValueCC = JSON.stringify(usersCC); //CC一覧のマージ対象項目をJSON文字列化\n let class152 = JSON.stringify($('#Results_Class152').val()); //CC一覧\n\n //前と内容が同じ場合は上書きしない\n if (mergeValueCC !== class152) {\n $p.set($('#Results_Class152'), mergeValueCC); //CC一覧\n }\n\n //担当者一覧・CC一覧のマージ(重複除去)\n let usersAll = [];\n users1.concat(usersCC).forEach(function (v) {\n if (v && !usersAll.includes(v)) usersAll.push(v);\n });\n\n let mergeValueAll = JSON.stringify(usersAll); //担当者一覧・CC一覧のマージ対象項目をJSON文字列化\n let class153 = JSON.stringify($('#Results_Class153').val()); //担当者・CC一覧\n\n //前と内容が同じ場合は上書きしない\n if (mergeValueAll !== class153) {\n $p.set($('#Results_Class153'), mergeValueAll); //担当者・CC一覧\n }\n\n //登録者(依頼者)+担当者・CC一覧をマージしてClass154(依頼者・担当者・CC一覧)へ保存\n $p.mergeClass154(usersAll);\n}\n\n//----------------------------------------------------------------------\n//重複を除いてClass154(依頼者・担当者・CC一覧、複数選択・非表示)へ保存する\n$p.mergeClass154 = function (usersAll) {\n let classBVal = $('#Results_ClassB').val(); //登録者(依頼者)\n\n let merged = [];\n if (classBVal && !merged.includes(classBVal)) merged.push(classBVal);\n usersAll.forEach(function (v) {\n if (v && !merged.includes(v)) merged.push(v);\n });\n\n let mergeValue = JSON.stringify(merged);\n let class154 = JSON.stringify($('#Results_Class154').val()); //依頼者・担当者・CC一覧\n\n //前と内容が同じ場合は上書きしない\n if (mergeValue !== class154) {\n $p.set($('#Results_Class154'), mergeValue); //依頼者・担当者・CC一覧\n }\n}\n\n//----------------------------------------------------------------------\n//マスターシート・エリア・契約ブランド・契約営業所連携\n//\n//AutoPostBack(Links設定によるサーバー側自動転記)は処理負荷を避けるため全廃し、\n//クライアントスクリプトで転記を行う。\n// ・ClassY(マスターシート): 選択のたびに$p.apiGetでその場でレコード取得(対象レコードが多いため)\n// ・Class022/023/031(エリア・契約ブランド・契約営業所): BeforeOpeningPageのServerScriptが\n// 事前に全件取得しhiddenへ格納済みのデータをクライアント側で逆引きするだけ(apiGetは呼ばない)\n//\n//上書きルール(共通):マスターシートからの転記は常に全上書きする(転記元が空欄なら転記先も空欄に\n//する)。ただし重複チェックキー(Class001/002/003/004/022)は、登録完了後(Status=200/900/910/920)\n//は差し替えない(ReadOnly化されているため、ClassY選択時の$p.on('change','ClassY',...)参照)。\n//\n//ClassY(マスターシート)自体は、登録完了(Status=200)以降かつ既に選択済みの場合のみ\n//選択変更不可にする(未選択のままなら登録完了後も選択可能にする、$p.toggleClassYLock参照)\n\n//ServerScriptが埋め込んだhiddenのマスタデータ(エリア/契約ブランド/契約営業所)\nlet areaMasterData = {};\nlet brandMasterData = {};\nlet officeMasterData = {};\n\n$p.loadStaticMasters = function () {\n areaMasterData = $('#areaMaster').val() ? JSON.parse($('#areaMaster').val()) : {};\n brandMasterData = $('#brandMaster').val() ? JSON.parse($('#brandMaster').val()) : {};\n officeMasterData = $('#officeMaster').val() ? JSON.parse($('#officeMaster').val()) : {};\n}\n\n//APIレスポンス($p.apiGet結果)から、列名に応じたHash経由で値を取り出す\n$p.getApiRecordValue = function (record, fieldName) {\n if (fieldName === 'ResultId' || fieldName === 'Title' || fieldName === 'ItemTitle') {\n return record[fieldName];\n }\n let hashKey =\n fieldName.indexOf('Date') === 0 ? 'DateHash' :\n fieldName.indexOf('Num') === 0 ? 'NumHash' :\n fieldName.indexOf('Description') === 0 ? 'DescriptionHash' :\n fieldName.indexOf('Check') === 0 ? 'CheckHash' :\n fieldName.indexOf('Attachments') === 0 ? 'AttachmentsHash' :\n 'ClassHash';\n return record[hashKey] ? record[hashKey][fieldName] : undefined;\n}\n\n//転記先1項目へ値をセットする(常に上書き、転記元が空欄なら転記先も空欄にする)\n$p.applyLookupValue = function (toColumn, value) {\n let $target = $('#Results_' + toColumn);\n if (!$target.length) return;\n $p.set($target, value || '');\n}\n\n//----------------------------------------------------------------------\n//ClassY(マスターシート、SiteId:189112)選択時の転記\n//重複チェックキー(Class001姓/Class002名/Class003姓カナ/Class004名カナ/Class022エリア)も\n//転記対象に含めるが、登録完了後(Status=200/900/910/920)はReadOnly化されているため\n//転記対象から除外する(それ以外の項目はStatusに関わらず常に上書き、applyLookupValueは使わない)。\n$p.duplicationKeyColumns = ['Class001', 'Class002', 'Class003', 'Class004', 'Class022'];\n\n$p.classYFieldMap = [\n { from: 'ClassA', to: 'ClassZ' },\n { from: 'Class001', to: 'Class001' },\n { from: 'Class002', to: 'Class002' },\n { from: 'Class003', to: 'Class003' },\n { from: 'Class004', to: 'Class004' },\n { from: 'Class009', to: 'Class005' },\n { from: 'Class010', to: 'Class006' },\n { from: 'Class011', to: 'Class007' },\n { from: 'Class012', to: 'Class008' },\n { from: 'Class017', to: 'Class009' },\n { from: 'Class018', to: 'Class010' },\n { from: 'Class019', to: 'Class011' },\n { from: 'Class020', to: 'Class012' },\n { from: 'Class029', to: 'Class021' },\n { from: 'ClassW', to: 'Class022' },\n { from: 'Class033', to: 'Class023' },\n { from: 'Class040', to: 'Class024' },\n { from: 'Class043', to: 'Class025' },\n { from: 'ClassF', to: 'Class031' },\n { from: 'ClassG', to: 'Class032' },\n { from: 'ClassH', to: 'Class033' },\n { from: 'ClassI', to: 'Class034' },\n { from: 'ClassL', to: 'Class035' },\n { from: 'ClassK', to: 'Class036' },\n { from: 'ClassJ', to: 'Class037' },\n { from: 'Date063', to: 'Date001' },\n { from: 'DateH', to: 'Date002' }\n];\n\n$p.on('change', 'ClassY', function () {\n let newVal = $('#Results_ClassY').val();\n\n if (newVal) {\n $p.apiGet({\n 'id': newVal,\n 'async': false,\n 'done': function (data) {\n if (!data.Response || !data.Response.Data || !data.Response.Data[0]) {\n console.log('マスターシートのレコード取得に失敗しました');\n $p.ex.setMyMessage('new-status-red', 'データの取得に失敗しました。営業積算へお問い合わせください');\n return;\n }\n //Class022/023/031(エリア・契約ブランド・契約営業所)がClassY経由で更新された場合、\n //$p.setのtrigger('change')により各項目のchangeハンドラが連鎖発火し、\n //ClassM/ClassN/Class038への転記も自動的に行われる想定\n let record = data.Response.Data[0];\n let status = $('#Results_Status').val();\n let statusLocked = ['200', '900', '910', '920'].includes(status); //登録完了後\n\n $p.classYFieldMap.forEach(function (m) {\n //重複チェックキーは登録完了後(ReadOnly化されている間)は差し替えない\n if (statusLocked && $p.duplicationKeyColumns.includes(m.to)) return;\n\n let value = $p.getApiRecordValue(record, m.from);\n if (m.from === 'Date063' || m.from === 'DateH') {\n value = $p.formatMasterDateForLookup(value); //yyyy/mm/dd変換(規定外日付は空欄)\n }\n $p.set($('#Results_' + m.to), value || ''); //転記元が空欄でも空欄で差し替える\n });\n\n //案件状況(ClassS)を契約コード(ClassZ)の転記結果に応じて自動判定\n $p.judgeClassS();\n },\n 'fail': function (data) {\n console.log('マスターシートのレコード取得に失敗しました', data);\n $p.ex.setMyMessage('new-status-red', 'データの取得に失敗しました。営業積算へお問い合わせください');\n }\n });\n } else {\n //マスターシート選択解除 → 未契約\n $p.judgeClassS();\n }\n});\n\n//----------------------------------------------------------------------\n//ClassY転記の日付項目(Date063→Date001, DateH→Date002)をyyyy/mm/dd形式へ変換する。\n//マスターシート側で未入力の日付が1899-12-31等の規定外の値として入っているケースがあるため、\n//西暦1900年より前の値は未入力扱いとして空欄にする。\n$p.formatMasterDateForLookup = function (value) {\n if (!value) return '';\n let d = new Date(value);\n if (isNaN(d.getTime()) || d.getFullYear() < 1900) return '';\n let pad2 = function (n) { return ('0' + n).slice(-2); };\n return d.getFullYear() + '/' + pad2(d.getMonth() + 1) + '/' + pad2(d.getDate());\n}\n\n//----------------------------------------------------------------------\n//案件状況(ClassS)の自動判定\n//マスターシート(ClassY)未選択の場合は未契約。選択済みの場合は、転記された契約コード(ClassZ)が\n//\"9999AAABB\"(未契約扱いのダミーコード)なら未契約、それ以外なら契約済みと判定する。\n//自動判定後もClassS自体は通常項目のまま(読取り専用化しない)なので、手入力での変更を妨げない。\n$p.judgeClassS = function () {\n let classYVal = $('#Results_ClassY').val();\n let classZVal = $('#Results_ClassZ').val();\n let judged = (!classYVal || classZVal === '9999AAABB') ? '0' : '1';\n $p.set($('#Results_ClassS'), judged);\n}\n\n//----------------------------------------------------------------------\n//Class022(エリア、SiteId:210699)→ ClassM(エリア記号)転記\n//Class022自身は重複チェックキーのため、この項目自体はロック対象・必須のまま\n$p.applyAreaMasterLookup = function () {\n let newVal = $('#Results_Class022').val();\n $p.applyLookupValue('ClassM', newVal ? areaMasterData[newVal] : '');\n}\n\n$p.on('change', 'Class022', function () {\n $p.applyAreaMasterLookup();\n});\n\n//----------------------------------------------------------------------\n//Class023(契約ブランド、SiteId:109100)選択時の転記 → ClassN(ブランド記号)\n$p.on('change', 'Class023', function () {\n let newVal = $('#Results_Class023').val();\n $p.applyLookupValue('ClassN', newVal ? brandMasterData[newVal] : '');\n});\n\n//----------------------------------------------------------------------\n//Class031(契約営業所、SiteId:96243)選択時の転記 → Class038(所属長)\n$p.on('change', 'Class031', function () {\n let newVal = $('#Results_Class031').val();\n $p.applyLookupValue('Class038', newVal ? officeMasterData[newVal] : '');\n});\n", "Id": 1 }, { "Title": "02_プロセス処理スクリプト.js", "New": true, "Edit": true, "Body": "/*\n@config :\n@filename : 02_プロセス処理スクリプト.js\n@title : 02_プロセス処理スクリプト.js\n@name :\n@siteIds :\n@siteTitles : プロセス実行前の処理\n@disabled: false\n*/\n\n//プロセスボタンから呼び出す共通ディスパッチャ(雛形)\n//Process定義側のOnClickは $p.ex.processScript($(this)); の形(ボタン要素そのものを渡す形)で呼び出す想定。\n//procNum(数値文字列)ではなく、ボタンの表示ラベル文字列(procName)で処理を振り分ける方針(②サイトに倣う)。\n//プロセス再設計時、switch内にプロセス名ごとのcaseを追加していく。\n$p.ex.processScript = async function (target) {\n let $btn = $(target);\n if (!$btn.length) {\n console.log('processScript: 対象ボタンが取得できませんでした');\n return false;\n }\n\n let procName = $btn.text().replace(/^\\s+/, '').trim();\n console.log('processScript ' + procName);\n\n //確認ダイアログを出さないプロセス名。ここにprocNameを追加すると、そのプロセスはconfirmをスキップして即実行する\n let noConfirmProcesses = [];\n\n switch (procName) {\n case '登録完了':\n //実行者:登録者(本人限定、Process側View.ColumnFilterHash: ClassB=Ownで担保)\n //要入力チェックあり(Process側ValidateInputsで担保)\n //確認プロンプトあり\n let popMessage1 = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (!confirm(popMessage1)) return;\n break;\n case '依頼受付終了':\n case '物件取消':\n //確認プロンプトあり。OK後、重複チェックキー(Class200)へタイムスタンプを付記し、\n //同一施主・エリアでの新規物件登録がNoDuplication設定でブロックされないようにする\n //($p.appendDuplicationKeyTimestampは1_01_基本スクリプト.js参照)\n let popMessage2 = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (!confirm(popMessage2)) return;\n $p.appendDuplicationKeyTimestamp();\n break;\n case '登録完了へ戻す':\n //確認プロンプトあり。OK後、付記済みの重複チェックキー(Class200)のタイムスタンプを除去し、\n //元のキーへ戻す($p.removeDuplicationKeyTimestampは1_01_基本スクリプト.js参照)\n let popMessage3 = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (!confirm(popMessage3)) return;\n $p.removeDuplicationKeyTimestamp();\n break;\n default:\n let popMessage = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (!noConfirmProcesses.includes(procName) && !confirm(popMessage)) return;\n break;\n }\n\n //プロセス実行\n $p.execProcess($btn);\n\n //プロセス側で設定した入力検証(ValidateInputs)が未入力エラーになった場合、\n //Pleasanterが対象項目へを\n //動的追加する。これを拾い、for属性から通常のフィールドラベル(class=\"error\"でない方)を逆引きして\n //まとめて下部にアラート表示する(必須項目名はスクリプト内にハードコードしない、②サイトと同じ方式)\n setTimeout(function () {\n let $errorLabels = $('label.error[id$=\"-error\"]');\n if ($errorLabels.length) {\n let labelTexts = [];\n $errorLabels.each(function () {\n let forAttr = $(this).attr('for');\n let $fieldLabel = $('label[for=\"' + forAttr + '\"]').not('.error').first();\n labelTexts.push($fieldLabel.length ? $fieldLabel.text().trim() : forAttr);\n });\n $p.ex.setMyMessage('new-status-red', labelTexts.join('、') + ' は必須項目です。入力してください。');\n }\n }, 300);\n}\n", "Id": 2 } ], "ServerScripts": [ { "Title": "マスターデータ取得", "Name": "マスターデータ取得", "BeforeOpeningPage": true, "Body": "try {\n context.Log('マスターデータ取得(エリア・契約ブランド・契約営業所)開始');\n getAreaMaster();\n getBrandMaster();\n getOfficeMaster();\n} catch (error) {\n context.Log(error);\n}\n\n//エリアマスタ取得(SiteId:210699)\n//Class022(エリア)選択時、クライアント側でこのデータを逆引きしてClassM(エリア記号)へ転記する\nfunction getAreaMaster() {\n let masterTableId = '210699';\n let results = items.Get(masterTableId);\n if (results.Length === 0) {\n context.Log('エリアマスタが見つかりませんでした');\n return;\n }\n\n let areaMaster = {};\n for (let item of results) {\n areaMaster[item.ResultId] = item.ClassA;\n }\n\n hidden.Add('areaMaster', JSON.stringify(areaMaster));\n context.Log('エリアマスタを取得しました');\n}\n\n//契約ブランドマスタ取得(SiteId:109100)\n//Class023(契約ブランド)選択時、クライアント側でこのデータを逆引きしてClassN(ブランド記号)へ転記する\nfunction getBrandMaster() {\n let masterTableId = '109100';\n let results = items.Get(masterTableId);\n if (results.Length === 0) {\n context.Log('契約ブランドマスタが見つかりませんでした');\n return;\n }\n\n let brandMaster = {};\n for (let item of results) {\n brandMaster[item.ResultId] = item.ClassA;\n }\n\n hidden.Add('brandMaster', JSON.stringify(brandMaster));\n context.Log('契約ブランドマスタを取得しました');\n}\n\n//契約営業所マスタ取得(SiteId:96243)\n//Class031(契約営業所)選択時、クライアント側でこのデータを逆引きしてClass038(所属長)へ転記する\nfunction getOfficeMaster() {\n let masterTableId = '96243';\n let results = items.Get(masterTableId);\n if (results.Length === 0) {\n context.Log('契約営業所マスタが見つかりませんでした');\n return;\n }\n\n let officeMaster = {};\n for (let item of results) {\n officeMaster[item.ResultId] = item.ClassK;\n }\n\n hidden.Add('officeMaster', JSON.stringify(officeMaster));\n context.Log('契約営業所マスタを取得しました');\n}\n", "Id": 1 } ], "AutoVerUpType": 3, "AllowCopy": false, "HideLink": true, "TitleSeparator": "■", "NoDisplayIfReadOnly": false, "NotInheritPermissionsWhenCreatingSite": false, "PermissionForCreating": { "Class154": 4 }, "PermissionForUpdating": { "Class154": 4 }, "CreateColumnAccessControls": [ { "ColumnName": "Class199", "Depts": [ 25 ] } ], "ReadColumnAccessControls": [ { "ColumnName": "Class199", "Depts": [ 25 ] } ], "UpdateColumnAccessControls": [ { "ColumnName": "Class199", "Depts": [ 25 ] } ] }, "Publish": false, "DisableCrossSearch": false, "Comments": [] }, { "TenantId": 1, "SiteId": 504322, "Title": "【デモ版】②問い合わせ内容管理", "SiteName": "", "SiteGroupName": "", "Body": "・2026.3.10作成", "GridGuide": "新規依頼は【①物件登録情報】の各施主ページ内から行ってください!\n※②問い合わせ内容管理ページの「+新規作成」から依頼するとエラーが出ます\n\n■LINEWORKS:[営業積算相談窓口](https://line.worksmobile.com/message/send?userNoList=800300000001353&version=25&type=counselor) ※窓口の対応内容や対応時間の確認は[こちら](https://board.worksmobile.com/main/article/4080000000785782853?t=41276&boardNo=my&isShowFilesArea=false)\n※不明点がある場合や期日前倒し希望の場合は、窓口までご連絡ください\n※期日前倒し連絡がない場合は、対応できかねます\n■LINEWORKS掲示板:[営業積算関連情報ポータル](https://board.worksmobile.com/main/article/4080000000813091905?t=70969&boardNo=my&isShowFilesArea=false)", "EditorGuide": "新規依頼は【①物件登録情報】の各施主ページ内から行ってください!\n※②問い合わせ内容管理ページの「+新規作成」から依頼するとエラーが出ます\n\n■LINEWORKS:[営業積算相談窓口](https://line.worksmobile.com/message/send?userNoList=800300000001353&version=25&type=counselor) ※窓口の対応内容や対応時間の確認は[こちら](https://board.worksmobile.com/main/article/4080000000785782853?t=41276&boardNo=my&isShowFilesArea=false)\n※不明点がある場合や期日前倒し希望の場合は、窓口までご連絡ください\n※期日前倒し連絡がない場合は、対応できかねます\n■LINEWORKS掲示板:[営業積算関連情報ポータル](https://board.worksmobile.com/main/article/4080000000813091905?t=70969&boardNo=my&isShowFilesArea=false)", "CalendarGuide": "", "CrosstabGuide": "", "GanttGuide": "", "BurnDownGuide": "", "TimeSeriesGuide": "", "AnalyGuide": "", "KambanGuide": "", "ImageLibGuide": "", "ReferenceType": "Results", "ParentId": 504317, "InheritPermission": 504322, "SiteSettings": { "Version": 1.017, "ReferenceType": "Results", "GridColumns": [ "ClassA", "ClassB", "Status", "ClassO", "CheckA", "ClassE", "ClassC", "DescriptionC", "Attachments031", "Check071", "Check072", "DescriptionF", "Attachments061", "Comments", "UpdatedTime" ], "FilterColumns": [ "Status", "Owner", "Class003", "Class004", "Class011", "Class062", "Class064", "Class101", "Class102", "Class103", "DateA", "Date081" ], "EditorColumnHash": { "General": [ "ResultId", "Ver", "Title", "ClassZ", "Comments", "ClassA", "ClassB", "ClassX", "ClassC", "ClassD", "_Section-1", "DateA", "DateJ", "ClassE", "CheckA", "ClassG", "ClassT", "ClassH", "ClassI", "DescriptionA", "Class088", "Check073", "Check074", "DateB", "DateC", "_Section-2", "Class001", "Class002", "Class003", "Class004", "Class005", "Class006", "_Section-3", "Class007", "Class031", "Class032", "Class033", "Class034", "Description031", "Class045", "Class050", "_Section-17", "Class038", "Class039", "Class040", "_Section-19", "DescriptionC", "_Section-18", "Attachments031", "Class052", "_Section-6", "Date061", "Class061", "Class062", "Date062", "Class063", "_Section-7", "Date063", "Class065", "Description061", "Description062", "_Links-504321", "Class153", "ClassY" ], "_Tab-2": [ "_Section-11", "Date081", "Class081", "Date082", "Class082", "Class083", "Class084", "Description051", "Status", "Class080", "_Section-12", "Class085", "Class086", "Date084", "Class087", "Date085", "Description081", "Description082", "Description083", "_Section-13", "Date090", "Class091", "Class089", "Description091", "Description092", "Description093", "Attachments101", "Num101", "Class101", "Class102", "Date103", "Class103", "Class095", "Description101" ], "_Tab-1": [ "Class071", "Description071", "Class075", "Date071", "_Section-8", "_Section-9", "Description075", "Attachments071", "Date073", "Class077", "Check071", "Num071", "_Section-10", "Description076", "Attachments072", "Check072", "Num072", "Date074" ], "_Tab-3": [ "_Section-14", "Description111", "Attachments111", "Attachments112", "Class111", "Attachments113", "_Section-15", "Date111" ] }, "GeneralTabLabelText": "問い合わせ情報", "TabLatestId": 4, "Tabs": [ { "LabelText": "質疑回答", "Id": 1 }, { "LabelText": "営業積算", "Id": 2 }, { "LabelText": "積算発注", "Id": 3 } ], "SectionLatestId": 19, "Sections": [ { "Id": 1, "LabelText": "案件情報", "AllowExpand": true, "Expand": true }, { "Id": 2, "LabelText": "物件情報", "AllowExpand": false, "Expand": true }, { "Id": 3, "LabelText": "問い合わせ内容 ※期日前倒しの連絡や相談は、営業積算窓口まで※", "AllowExpand": false, "Expand": true }, { "Id": 17, "LabelText": "", "AllowExpand": false, "Expand": true }, { "Id": 19, "LabelText": "", "AllowExpand": false, "Expand": true }, { "Id": 18, "LabelText": "", "AllowExpand": false, "Expand": true }, { "Id": 6, "LabelText": "営業積算 ※※読み取り専用※※", "AllowExpand": false, "Expand": true }, { "Id": 7, "LabelText": "見積回答結果 ※※読み取り専用※※", "AllowExpand": false, "Expand": true }, { "Id": 11, "LabelText": "受付処理", "AllowExpand": false, "Expand": true }, { "Id": 12, "LabelText": "遅延連絡", "AllowExpand": false, "Expand": true }, { "Id": 13, "LabelText": "算出回答結果", "AllowExpand": false, "Expand": true }, { "Id": 8, "LabelText": "質疑回答ログ", "AllowExpand": true, "Expand": true }, { "Id": 9, "LabelText": "営業積算からの質疑", "AllowExpand": false, "Expand": true }, { "Id": 10, "LabelText": "依頼者からの回答", "AllowExpand": false, "Expand": true }, { "Id": 14, "LabelText": "営業積算からの引継ぎ", "AllowExpand": false, "Expand": true }, { "Id": 15, "LabelText": "積算発注課管理", "AllowExpand": false, "Expand": true } ], "TitleColumns": [ "ClassA", "ClassB", "Class003", "Class004" ], "LinkColumns": [ "ClassA", "ClassB", "ClassC", "Class062", "DateA", "Class091", "Description061" ], "Columns": [ { "ColumnName": "ClassA", "LabelText": "親番", "NotInsertBlankChoice": true, "NoWrap": true, "ExtendedFieldCss": "code-readonly2", "CopyByDefault": true }, { "ColumnName": "Owner", "ChoicesText": "", "DefaultInput": "", "NoWrap": true, "SearchType": "ExactMatch" }, { "ColumnName": "ClassD", "LabelText": "主担当営業", "ChoicesText": "[[Users*]]", "UseSearch": true, "ExtendedFieldCss": "code-readonly2", "SearchType": "PartialMatch" }, { "ColumnName": "ClassE", "LabelText": "アップ希望時間", "GridLabelText": "アップ希望日時", "ChoicesText": "指定なし\n9:00\n9:30\n10:00\n10:30\n11:00\n11:30\n12:00\n12:30\n13:00\n13:30\n14:00\n14:30\n15:00\n15:30\n16:00\n16:30\n17:00\n17:30\n18:00", "NotInsertBlankChoice": true, "DefaultInput": "指定なし", "NoWrap": true, "GridDesign": "[DateA]\n[ClassE]", "SearchType": "PartialMatch" }, { "ColumnName": "ClassG", "LabelText": "現在の進捗", "ChoicesText": "0,商談~承認図\n1,承認図後・着工中(監督確認済/お客様請求可)", "ChoicesControlType": "Radio", "NoWrap": true, "SearchType": "PartialMatch" }, { "ColumnName": "ClassT", "LabelText": "現在の進捗(控え)", "Hide": true }, { "ColumnName": "ClassH", "LabelText": "現場の進捗", "ChoicesText": "0,承認図後~着工前\n1,着工中\n2,引渡し前", "ChoicesControlType": "Radio", "NoWrap": true, "SearchType": "PartialMatch" }, { "ColumnName": "ClassI", "LabelText": "必要な見積金額", "ChoicesText": "0,承認図時まで\n1,承認図以降", "ChoicesControlType": "Radio", "NoWrap": true, "SearchType": "PartialMatch" }, { "ColumnName": "DateA", "LabelText": "アップ希望日", "InputGuide": "土日祝日を除く5営業日以降" }, { "ColumnName": "CheckA", "LabelText": "営業積算相談窓口に相談済み", "NoWrap": true }, { "ColumnName": "DescriptionA", "LabelText": "問い合わせ経緯", "InputGuide": "(入力例)承認図時に決定していた商品が廃盤となり、商品の再選定が必要になったため", "ExtendedHtmlAfterControl": "
\n※承認図以降の問い合わせの場合は、「承認図時の内容」であっても必ず経緯を入力してください\n
", "AllowImage": false }, { "ColumnName": "DateB", "LabelText": "承認図予定日", "NoWrap": true, "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "DateC", "LabelText": "着工予定日", "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "Class001", "LabelText": "施主名", "ExtendedFieldCss": "code-readonly2", "FieldCss": "field-wide" }, { "ColumnName": "Class002", "LabelText": "建上地", "ExtendedFieldCss": "code-readonly2", "FieldCss": "field-wide" }, { "ColumnName": "Class003", "LabelText": "エリア", "ChoicesText": "[[210699]]", "ExtendedFieldCss": "code-readonly2", "Link": true, "SearchType": "PartialMatch" }, { "ColumnName": "Class004", "LabelText": "ブランド", "ChoicesText": "[[109100]]", "ExtendedFieldCss": "code-readonly2", "Link": true, "SearchType": "PartialMatch" }, { "ColumnName": "Class005", "LabelText": "建物種類", "ChoicesText": "平屋\n2階建て\n3階建て", "NoWrap": true, "ExtendedFieldCss": "code-readonly2", "SearchType": "PartialMatch" }, { "ColumnName": "Class006", "LabelText": "防火指定", "ChoicesText": "無\n準防火\n準耐火", "ExtendedFieldCss": "code-readonly2", "SearchType": "PartialMatch" }, { "ColumnName": "Class007", "LabelText": "問合せ種別", "ChoicesText": "マトリックス以外\nマトリックス", "NotInsertBlankChoice": true, "ChoicesControlType": "Radio", "ValidateRequired": true, "ExtendedHtmlAfterControl": "
\n※最初に問い合わせの種類を選択してください※\n
" }, { "ColumnName": "Status", "ChoicesText": "100,未依頼,未依頼,new-status-white\n200,新規依頼,新規依頼,new-status-light-orange\n400,受付済,受付済,new-status-orange\n450,依頼者質疑中,質疑中,new-status-yellow\n480,依頼者回答有,回答有,new-status-white\n500,積算対応中,積算対応中,new-status-green\n510,外部見積待ち,外部見積待ち,new-status-green\n520,社内確認中,社内確認中,new-status-green\n800,一部回答,一部回答,new-status-pink\n810,回答完了,回答完了,new-status-light-blue\n900,完了,完了,new-status-blue\n901,問合せ不要,問合せ不要,new-status-blue\n910,保留,保留,new-status-grey\n920,取消,取消,new-status-grey", "NoWrap": true }, { "ColumnName": "Class031", "LabelText": "メーカー", "InputGuide": "正式名称で入力してください(例)DAIKEN", "FieldCss": "field-wide" }, { "ColumnName": "Class038", "LabelText": "積算Ver.", "Description": "該当の積算バージョンを入力してください", "InputGuide": "(入力例)260211-AC-全-002", "NoWrap": true, "ExtendedHtmlAfterControl": "
\n※入力漏れ多いので注意!\n
" }, { "ColumnName": "Class040", "LabelText": "nexthouseシリーズ", "Description": "nexthouse提案の場合は選択してください", "ChoicesText": "LAVIE\nFAMILIE・PRIME\nCERAGRAN", "NotInsertBlankChoice": true, "ChoicesControlType": "Radio", "NoWrap": true, "ExtendedHtmlAfterControl": "
\n※nexthouseの場合のみ選択してください※\n
\n", "SearchType": "PartialMatch" }, { "ColumnName": "Class045", "LabelText": "標準仕様", "Description": "標準仕様からの変更差額を希望の場合は、該当の仕様をこちらへ入力してください", "InputGuide": "標準仕様からの変更差額を希望の場合は、該当の仕様をこちらへ入力してください(例)LIXIL ラシッサD階段", "ExtendedHtmlAfterControl": "
\n※標準仕様からの変更差額出しを希望する場合は、こちらに標準仕様を記載してください\n
", "FieldCss": "field-wide" }, { "ColumnName": "Class050", "LabelText": "前回の管理番号", "Description": "既出問い合わせからの変更の場合は、該当の番号を選択してください", "FieldCss": "field-wide" }, { "ColumnName": "Class052", "LabelText": "回答希望送付先", "ChoicesText": "[\n {\n \"TableName\": \"Users\",\n \"View\": {\n \"ColumnFilterExpressions\": {\n \"UserId\": \"=[@Class153]\"\n }\n }\n }\n]", "UseSearch": true, "MultipleSelections": true, "ExtendedHtmlAfterControl": "
\n※見積回答を送付して欲しい方を選択してください(選択ない場合は、依頼者と担当営業に回答送信します)\n
", "FieldCss": "field-wide" }, { "ColumnName": "Class061", "LabelText": "受付者", "ChoicesText": "[\n {\n \"TableName\": \"Users\",\n \"View\": {\n \"ColumnFilterHash\": {\n \"DeptId\": \"[\\\"25\\\"]\"\n },\n \"ColumnSorterHash\": {\n \"UserId\": \"asc\"\n }\n }\n }\n]", "UseSearch": true, "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "Date061", "LabelText": "受付日", "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "Date062", "LabelText": "見積依頼日", "NoWrap": true, "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "Class062", "LabelText": "状況", "ChoicesText": "100,未依頼,未依頼,new-status-white\n200,新規依頼,新規依頼,new-status-light-orange\n400,受付済,受付済,new-status-orange\n450,依頼者質疑中,質疑中,new-status-yellow\n480,依頼者回答有,回答有,new-status-white\n500,積算対応中,積算対応中,new-status-green\n510,外部見積待ち,外部見積待ち,new-status-green\n520,社内確認中,社内確認中,new-status-green\n800,一部回答,一部回答,new-status-pink\n810,回答完了,回答完了,new-status-light-blue\n900,完了,完了,new-status-blue\n901,問合せ不要,問合せ不要,new-status-blue\n910,保留,保留,new-status-grey\n920,取消,取消,new-status-grey", "NoWrap": true, "ExtendedFieldCss": "code-readonly2", "SearchType": "PartialMatch" }, { "ColumnName": "Class063", "LabelText": "見積依頼先", "ExtendedFieldCss": "code-readonly2", "FieldCss": "field-wide" }, { "ColumnName": "Date063", "LabelText": "見積受信日", "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "Class064", "LabelText": "採用状況", "ChoicesText": "採用\n不採用\n打合せ中", "ChoicesControlType": "Radio", "NoWrap": true, "Hide": true, "SearchType": "PartialMatch" }, { "ColumnName": "Class065", "LabelText": "見積種別", "ChoicesText": "概算\n正式", "ChoicesControlType": "Radio", "NoWrap": true, "ExtendedFieldCss": "code-readonly2", "SearchType": "PartialMatch" }, { "ColumnName": "Description061", "LabelText": "見積結果", "ExtendedFieldCss": "code-readonly2", "ExtendedControlCss": "code-readonly2", "AllowImage": false }, { "ColumnName": "Description062", "LabelText": "見積回答ファイル", "ExtendedFieldCss": "code-readonly2", "AllowImage": false }, { "ColumnName": "Date071", "LabelText": "質疑回答送信日時", "Hide": true }, { "ColumnName": "Date073", "LabelText": "質疑回答期日", "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "Date074", "LabelText": "回答確認日", "NoWrap": true, "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "Description071", "LabelText": "質疑回答データ保存用", "Hide": true, "AllowImage": false }, { "ColumnName": "Description075", "LabelText": "質疑内容", "AllowImage": false }, { "ColumnName": "Description076", "LabelText": "回答内容", "AllowImage": false }, { "ColumnName": "Attachments071", "LabelText": "質疑ファイル" }, { "ColumnName": "Attachments072", "LabelText": "回答ファイル" }, { "ColumnName": "Class071", "LabelText": "質疑回答ステータス", "ChoicesText": "0,質疑なし,質疑なし,new-status-white\n1,質疑あり,質疑あり,new-status-red\n2,回答あり,回答あり,new-status-yellow\n3,回答確認済み,回答確認済み,new-status-green", "DefaultInput": "0", "Hide": true, "SearchType": "PartialMatch" }, { "ColumnName": "Class075", "LabelText": "質疑回答送信者", "Hide": true }, { "ColumnName": "Date081", "LabelText": "受付日", "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "Date082", "LabelText": "見積依頼日", "NoWrap": true, "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "Date085", "LabelText": "返信予定日", "NoWrap": true }, { "ColumnName": "Date090", "LabelText": "見積受信日" }, { "ColumnName": "Date103", "LabelText": "返信日", "NoWrap": true, "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "Class081", "LabelText": "受付者", "ChoicesText": "[\n {\n \"TableName\": \"Users\",\n \"View\": {\n \"ColumnFilterHash\": {\n \"DeptId\": \"[\\\"25\\\"]\"\n },\n \"ColumnSorterHash\": {\n \"UserId\": \"asc\"\n }\n }\n }\n]", "UseSearch": true, "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "Class082", "LabelText": "見積依頼者", "ChoicesText": "[\n {\n \"TableName\": \"Users\",\n \"View\": {\n \"ColumnFilterHash\": {\n \"DeptId\": \"[\\\"25\\\"]\"\n },\n \"ColumnSorterHash\": {\n \"UserId\": \"asc\"\n }\n }\n }\n]", "UseSearch": true, "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "Class083", "LabelText": "見積依頼先", "FieldCss": "field-wide" }, { "ColumnName": "Class084", "LabelText": "見積備考", "FieldCss": "field-wide" }, { "ColumnName": "Description051", "LabelText": "受付処理備考" }, { "ColumnName": "Class085", "LabelText": "遅延送付先", "ChoicesText": "[\n {\n \"TableName\": \"Users\",\n \"View\": {\n \"ColumnFilterExpressions\": {\n \"UserId\": \"=[@Class153]\"\n }\n }\n }\n]", "UseSearch": true, "MultipleSelections": true, "FieldCss": "field-wide" }, { "ColumnName": "Class086", "LabelText": "遅延理由", "ChoicesText": "[\n {\n \"SiteId\": 504320,\n \"View\": {\n \"ColumnSorterHash\": {\n \"NumA\": \"asc\"\n }\n },\n \"Lookups\": [\n {\n \"From\": \"DescriptionA\",\n \"To\": \"Description081\"\n }\n ]\n }\n]", "AutoPostBack": true, "ColumnsReturnedWhenAutomaticPostback": "Description081", "SearchType": "PartialMatch" }, { "ColumnName": "Class087", "LabelText": "遅延連絡者", "ChoicesText": "[\n {\n \"TableName\": \"Users\",\n \"View\": {\n \"ColumnFilterHash\": {\n \"DeptId\": \"[\\\"25\\\"]\"\n },\n \"ColumnSorterHash\": {\n \"UserId\": \"asc\"\n }\n }\n }\n]", "UseSearch": true, "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "Description081", "LabelText": "遅延連絡内容", "AllowImage": false }, { "ColumnName": "Description083", "LabelText": "遅延連絡ログ" }, { "ColumnName": "Description091", "LabelText": "見積回答", "AllowImage": false }, { "ColumnName": "Description092", "LabelText": "別途費用・伝達事項", "AllowImage": false }, { "ColumnName": "Class101", "LabelText": "算出者", "ChoicesText": "[\n {\n \"TableName\": \"Users\",\n \"View\": {\n \"ColumnFilterHash\": {\n \"DeptId\": \"[\\\"25\\\"]\"\n },\n \"ColumnSorterHash\": {\n \"UserId\": \"asc\"\n }\n }\n }\n]", "UseSearch": true, "NoWrap": true }, { "ColumnName": "Class102", "LabelText": "チェック者", "ChoicesText": "[\n {\n \"TableName\": \"Users\",\n \"View\": {\n \"ColumnFilterHash\": {\n \"DeptId\": \"[\\\"25\\\"]\"\n },\n \"ColumnSorterHash\": {\n \"UserId\": \"asc\"\n }\n }\n }\n]", "UseSearch": true }, { "ColumnName": "Class103", "LabelText": "返信者", "ChoicesText": "[\n {\n \"TableName\": \"Users\",\n \"View\": {\n \"ColumnFilterHash\": {\n \"DeptId\": \"[\\\"25\\\"]\"\n },\n \"ColumnSorterHash\": {\n \"UserId\": \"asc\"\n }\n }\n }\n]", "UseSearch": true, "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "Description101", "LabelText": "見積回答ログ", "AllowImage": false }, { "ColumnName": "Attachments101", "LabelText": "見積回答ファイル" }, { "ColumnName": "Attachments111", "LabelText": "NET見積原本" }, { "ColumnName": "Attachments112", "LabelText": "算出根拠資料" }, { "ColumnName": "Class111", "LabelText": "採用書類", "FieldCss": "field-wide" }, { "ColumnName": "Attachments113", "LabelText": "その他" }, { "ColumnName": "Description111", "LabelText": "引継ぎ備考", "AllowImage": false }, { "ColumnName": "Num071", "LabelText": "質疑回数" }, { "ColumnName": "Num072", "LabelText": "回答回数" }, { "ColumnName": "Num101", "LabelText": "算出回答回数", "NoWrap": true }, { "ColumnName": "Date064", "LabelText": "使用期限", "Hide": true, "ExtendedHtmlAfterControl": "
\n※他物件使用ルールに基づいて使用してください\n
" }, { "ColumnName": "Attachments031", "LabelText": "依頼ファイル" }, { "ColumnName": "Date111", "LabelText": "データ出力日" }, { "ColumnName": "ClassC", "LabelText": "依頼者", "GridLabelText": "担当者", "ChoicesText": "[[Users*]]", "DefaultInput": "[[Self]]", "NoWrap": true, "ExtendedFieldCss": "code-readonly2", "GridDesign": "依頼者:[ClassC]\n営業担当:[ClassD]", "SearchType": "PartialMatch" }, { "ColumnName": "Class091", "LabelText": "見積種別", "ChoicesText": "概算\n正式", "ChoicesControlType": "Radio", "NoWrap": true, "SearchType": "PartialMatch" }, { "ColumnName": "Date091", "LabelText": "使用期限", "ExtendedHtmlAfterControl": "
\n※他物件使用ルールに基づいて使用してください\n
" }, { "ColumnName": "Class095", "LabelText": "回答送付先", "ChoicesText": "[\n {\n \"TableName\": \"Users\",\n \"View\": {\n \"ColumnFilterHash\": {\n \"Disabled\": \"false\"\n },\n \"ColumnFilterExpressions\": {\n \"UserId\": \"=[@Class153]\"\n }\n }\n }\n]", "MultipleSelections": true, "FieldCss": "field-wide" }, { "ColumnName": "Class077", "LabelText": "質疑送付先", "ChoicesText": "[\n {\n \"TableName\": \"Users\",\n \"View\": {\n \"ColumnFilterExpressions\": {\n \"UserId\": \"=[@Class153]\"\n }\n }\n }\n]", "UseSearch": true, "MultipleSelections": true, "FieldCss": "field-wide" }, { "ColumnName": "UpdatedTime", "GridDesign": "[UpdatedTime]\n[Updator]" }, { "ColumnName": "ClassO", "GridLabelText": "施主情報", "GridDesign": "[Class001]\n[Class002]\n[Class004]" }, { "ColumnName": "DescriptionC", "LabelText": "依頼内容プレビュー", "Description": "依頼内容マージ", "ExtendedHtmlAfterControl": "
\n※こちらは上記依頼項目の内容を自動的にまとめた確認欄です。
\n修正する場合は、上のメーカー・商品名・品番などの項目を編集してください。\n
" }, { "ColumnName": "DescriptionF", "GridLabelText": "見積回答", "GridDesign": "[Description091]\n[Description092]" }, { "ColumnName": "Class032", "LabelText": "商品名", "Description": "正しい商品名を入力してください(例)イエリア 格子間仕切", "InputGuide": "正しい商品名を入力してください(例)イエリア 格子間仕切", "FieldCss": "field-wide" }, { "ColumnName": "Class033", "LabelText": "品番", "Description": "正しい品番を入力してください(例)QW404-■■", "InputGuide": "正しい品番を入力してください(例)QW404-■■", "FieldCss": "field-wide" }, { "ColumnName": "Description031", "LabelText": "依頼内容補足", "Description": "メーカー・商品名・品番以外に補足がある場合は、こちらに詳細を入力してください。", "InputGuide": "メーカー・商品名・品番以外に補足がある場合は、こちらに詳細を入力してください。", "AllowImage": false }, { "ColumnName": "Class080", "LabelText": "問い合わせジャンル", "ChoicesText": "以下から選択してください\nA.基本\nB.工法\nC.基礎\nD.床材\nE.断熱材・バルコニー\nF.外壁・軒天・タイル\nG.内部建材\nH.マトリックス\nI.造作家具・建具・洗面 他", "NotInsertBlankChoice": true, "NoWrap": true, "SearchType": "PartialMatch" }, { "ColumnName": "Title", "LabelText": "レコード名" }, { "ColumnName": "Class039", "LabelText": "マトリックスサイズ", "InputGuide": "(入力例)7×13", "ChoicesControlType": "Radio", "NoWrap": true }, { "ColumnName": "ClassZ", "LabelText": "テスト・リンク用", "ChoicesText": "[\n {\n \"SiteId\": 504321,\n \"NotReturnParentRecord\": true,\n \"Lookups\": [\n {\n \"From\": \"ClassA\",\n \"To\": \"ClassA\"\n },\n {\n \"From\": \"Class032\",\n \"To\": \"ClassD\"\n },\n {\n \"From\": \"Date001\",\n \"To\": \"DateB\"\n },\n {\n \"From\": \"Date002\",\n \"To\": \"DateC\"\n },\n {\n \"From\": \"Class015\",\n \"To\": \"Class001\"\n },\n {\n \"From\": \"Class021\",\n \"To\": \"Class002\"\n },\n {\n \"From\": \"Class022\",\n \"To\": \"Class003\"\n },\n {\n \"From\": \"Class023\",\n \"To\": \"Class004\"\n },\n {\n \"From\": \"Class025\",\n \"To\": \"Class005\"\n },\n {\n \"From\": \"Class024\",\n \"To\": \"Class006\"\n },\n {\n \"From\": \"Class153\",\n \"To\": \"Class153\"\n },\n {\n \"From\": \"Class153\",\n \"To\": \"Class052\"\n },\n {\n \"From\": \"Class153\",\n \"To\": \"Class077\"\n },\n {\n \"From\": \"Class153\",\n \"To\": \"Class085\"\n },\n {\n \"From\": \"Class153\",\n \"To\": \"Class095\"\n }\n ]\n }\n]", "Hide": true, "AutoPostBack": true, "ColumnsReturnedWhenAutomaticPostback": "ClassA,ClassD,DateB,DateC,Class001,Class002,Class003,Class004,Class005,Class006,Class153,Class052,Class077,Class085,Class095", "FieldCss": "field-wide", "SearchType": "PartialMatch" }, { "ColumnName": "Class034", "LabelText": "施工範囲・箇所", "Description": "施工場所を入力してください ※複数パターンある場合は『A:●●、B:■■』のようにわかるように記載してください", "InputGuide": "施工場所を入力してください ※複数パターンある場合は『A:●●、B:■■』のようにわかるように記載してください", "FieldCss": "field-wide" }, { "ColumnName": "Date084", "LabelText": "遅延連絡日", "NoWrap": true, "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "DateJ", "LabelText": "選択可最短日", "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "ClassB", "LabelText": "子番", "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "ClassX", "LabelText": "連番処理", "NoWrap": true, "Hide": true, "AutoNumberingFormat": "[ClassA]-[nnn]", "AutoNumberingResetType": "String" }, { "ColumnName": "Description082", "LabelText": "遅延連絡内容(控え)", "Hide": true }, { "ColumnName": "Check071", "LabelText": "質疑あり", "NoWrap": true, "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "Check072", "LabelText": "回答あり", "NoWrap": true, "ExtendedFieldCss": "code-readonly2" }, { "ColumnName": "Class153", "LabelText": "担当者・CC一覧", "ChoicesText": "[[Users*]]\n", "UseSearch": true, "MultipleSelections": true, "Hide": true, "FieldCss": "field-wide" }, { "ColumnName": "ClassY", "LabelText": "依頼者・担当者・CC一覧", "ChoicesText": "[[Users*]]", "MultipleSelections": true, "Hide": true, "FieldCss": "field-wide" }, { "ColumnName": "Class088", "LabelText": "担当監督", "ChoicesText": "[[210712]]", "UseSearch": true, "Link": true, "SearchType": "PartialMatch" }, { "ColumnName": "Check073", "LabelText": "稟議ではないことを確認済み", "NoWrap": true }, { "ColumnName": "Check074", "LabelText": "承認図後追加変更契約 定義書①~④以外である", "NoWrap": true, "FieldCss": "field-wide" }, { "ColumnName": "Class089", "LabelText": "不要理由", "ChoicesText": "[\n {\n \"SiteId\": 504319,\n \"View\": {\n \"ColumnSorterHash\": {\n \"NumA\": \"asc\"\n }\n }\n }\n]", "SearchType": "PartialMatch" } ], "Links": [ { "ColumnName": "Class003", "SiteId": 210699 }, { "ColumnName": "Class004", "SiteId": 109100 }, { "ColumnName": "Class086", "SiteId": 504320, "View": { "Id": 0, "ColumnSorterHash": { "NumA": "asc" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "Lookups": [ { "From": "DescriptionA", "To": "Description081" } ], "JsonFormat": true }, { "TableName": "Users", "ColumnName": "Class052", "SiteId": 0, "View": { "Id": 0, "ColumnFilterExpressions": { "UserId": "=[@Class153]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "JsonFormat": true }, { "TableName": "Users", "ColumnName": "Class077", "SiteId": 0, "View": { "Id": 0, "ColumnFilterExpressions": { "UserId": "=[@Class153]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "JsonFormat": true }, { "TableName": "Users", "ColumnName": "Class085", "SiteId": 0, "View": { "Id": 0, "ColumnFilterExpressions": { "UserId": "=[@Class153]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "JsonFormat": true }, { "TableName": "Users", "ColumnName": "Class095", "SiteId": 0, "View": { "Id": 0, "ColumnFilterHash": { "Disabled": "false" }, "ColumnFilterExpressions": { "UserId": "=[@Class153]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "JsonFormat": true }, { "ColumnName": "ClassZ", "SiteId": 504321, "NotReturnParentRecord": true, "Lookups": [ { "From": "ClassA", "To": "ClassA" }, { "From": "Class032", "To": "ClassD" }, { "From": "Date001", "To": "DateB" }, { "From": "Date002", "To": "DateC" }, { "From": "Class015", "To": "Class001" }, { "From": "Class021", "To": "Class002" }, { "From": "Class022", "To": "Class003" }, { "From": "Class023", "To": "Class004" }, { "From": "Class025", "To": "Class005" }, { "From": "Class024", "To": "Class006" }, { "From": "Class153", "To": "Class153" }, { "From": "Class153", "To": "Class052" }, { "From": "Class153", "To": "Class077" }, { "From": "Class153", "To": "Class085" }, { "From": "Class153", "To": "Class095" } ], "JsonFormat": true }, { "TableName": "Users", "ColumnName": "Class081", "SiteId": 0, "View": { "Id": 0, "ColumnFilterHash": { "DeptId": "[\"25\"]" }, "ColumnSorterHash": { "UserId": "asc" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "JsonFormat": true }, { "TableName": "Users", "ColumnName": "Class082", "SiteId": 0, "View": { "Id": 0, "ColumnFilterHash": { "DeptId": "[\"25\"]" }, "ColumnSorterHash": { "UserId": "asc" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "JsonFormat": true }, { "TableName": "Users", "ColumnName": "Class087", "SiteId": 0, "View": { "Id": 0, "ColumnFilterHash": { "DeptId": "[\"25\"]" }, "ColumnSorterHash": { "UserId": "asc" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "JsonFormat": true }, { "TableName": "Users", "ColumnName": "Class101", "SiteId": 0, "View": { "Id": 0, "ColumnFilterHash": { "DeptId": "[\"25\"]" }, "ColumnSorterHash": { "UserId": "asc" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "JsonFormat": true }, { "TableName": "Users", "ColumnName": "Class102", "SiteId": 0, "View": { "Id": 0, "ColumnFilterHash": { "DeptId": "[\"25\"]" }, "ColumnSorterHash": { "UserId": "asc" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "JsonFormat": true }, { "TableName": "Users", "ColumnName": "Class103", "SiteId": 0, "View": { "Id": 0, "ColumnFilterHash": { "DeptId": "[\"25\"]" }, "ColumnSorterHash": { "UserId": "asc" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "JsonFormat": true }, { "ColumnName": "Class088", "SiteId": 210712 }, { "ColumnName": "Class089", "SiteId": 504319, "View": { "Id": 0, "ColumnSorterHash": { "NumA": "asc" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "JsonFormat": true } ], "Processes": [ { "Id": 1, "Name": "新規依頼", "DisplayName": "積算へ依頼", "CurrentStatus": 100, "ChangedStatus": 200, "Description": "依頼者", "OnClick": "$p.ex.processScript($(this));", "View": { "Id": 0, "ColumnFilterHash": { "ClassC": "[\"Own\"]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "Notifications": [ { "Type": 1, "Subject": "【デモ版】【営業積算】[ClassA]-[ClassB] [Class001]様 : 新規依頼", "Address": "e-sekisan@next-hd.co.jp", "CcAddress": "[ClassC]", "MediaType": "application/json", "Body": "【デモ版】\n依頼者より新規依頼が届きました。\n\n内容を確認し、受付処理をお願いします。\n\n{Url}\n\n----------\n親番:[ClassA]\n子番:[ClassB]\n施主名:[Class001]\n----------\n\n■■■", "BeforeCondition": 0, "AfterCondition": 0, "Expression": 0, "Id": 1 } ] }, { "Id": 2, "Name": "受付", "DisplayName": "受付", "CurrentStatus": 200, "ChangedStatus": 400, "Description": "積算担当", "OnClick": "$p.ex.processScript($(this));", "Depts": [ 25 ], "View": { "Id": 0, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 } }, { "Id": 3, "Name": "質疑送信", "DisplayName": "質疑送信", "CurrentStatus": -1, "ChangedStatus": 450, "Description": "積算担当", "OnClick": "$p.ex.processScript($(this));", "Depts": [ 25 ], "View": { "Id": 0, "ColumnFilterHash": { "Status": "[\"100\",\"400\",\"450\",\"480\",\"500\",\"510\",\"520\",\"800\"]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "Notifications": [ { "Type": 1, "Subject": "【デモ版】【営業積算】[ClassA]-[ClassB] [Class001]様 : 質疑送信", "Address": "[ClassC]", "CcAddress": "[Class077]", "MediaType": "application/json", "Body": "【デモ版】\n営業積算より\n依頼内容についての質疑が届きました。\n\n下記URLより確認し、該当の質疑回答欄へ回答を入力してください。\n\n※このメールは送信専用です。\n 本メールに返信いただいても、内容は確認できませんのでご了承ください。\n お問い合わせは、営業積算窓口までご連絡ください。\n\n\n{Url}\n\n----------\n親番:[ClassA]\n子番:[ClassB]\n施主名:[Class001]\n----------\n\n【質疑回答期日】:[Date073]\n\n営業積算からの質疑:\n[Description075]\n\n----------\n\n■■■", "BeforeCondition": 0, "AfterCondition": 0, "Expression": 0, "Id": 1 } ] }, { "Id": 4, "Name": "回答送信", "DisplayName": "回答送信", "CurrentStatus": 450, "ChangedStatus": 480, "Description": "依頼者", "OnClick": "$p.ex.processScript($(this));", "View": { "Id": 0, "ColumnFilterHash": { "ClassY": "[\"Own\"]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "Notifications": [ { "Type": 1, "Subject": "【デモ版】【営業積算】[ClassA]-[ClassB] [Class001]様 : 回答送信", "Address": "e-sekisan@next-hd.co.jp", "CcAddress": "[ClassC], [Class077]", "MediaType": "application/json", "Body": "【デモ版】\n依頼者より\n質疑回答が届きました。\n\n内容を確認してください。\n\n\n{Url}\n\n----------\n親番:[ClassA]\n子番:[ClassB]\n施主名:[Class001]\n----------\n\n依頼者からの回答:\n[Description076]\n\n----------\n\n■■■", "BeforeCondition": 0, "AfterCondition": 0, "Expression": 0, "Id": 1 } ] }, { "Id": 5, "Name": "質疑回答削除", "DisplayName": "質疑回答削除", "CurrentStatus": 450, "ChangedStatus": 450, "Description": "積算担当", "OnClick": "$p.ex.processScript($(this));", "Depts": [ 25 ], "View": { "Id": 0, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "Notifications": [ { "Type": 1, "Subject": "【デモ版】【営業積算】[ClassA]-[ClassB] [Class001]様 : 質疑回答削除", "Address": "[ClassC]", "CcAddress": "[Class077]", "MediaType": "application/json", "Body": "【デモ版】\n営業積算より\n質疑回答の内容が削除されました。\n\n再度ご回答をお願いする場合がございます。\n下記URLよりご確認ください。\n\n\n{Url}\n\n----------\n親番:[ClassA]\n子番:[ClassB]\n施主名:[Class001]\n----------\n\n■■■", "BeforeCondition": 0, "AfterCondition": 0, "Expression": 0, "Id": 1 } ] }, { "Id": 6, "Name": "積算対応中へ", "DisplayName": "積算対応中へ", "CurrentStatus": -1, "ChangedStatus": 500, "Description": "積算担当", "OnClick": "$p.ex.processScript($(this));", "Depts": [ 25 ], "View": { "Id": 0, "ColumnFilterHash": { "Status": "[\"400\",\"450\",\"480\",\"500\",\"510\",\"520\"]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 } }, { "Id": 7, "Name": "外部見積待ちへ", "DisplayName": "外部見積待ちへ", "CurrentStatus": -1, "ChangedStatus": 510, "Description": "積算担当", "OnClick": "$p.ex.processScript($(this));", "Depts": [ 25 ], "View": { "Id": 0, "ColumnFilterHash": { "Status": "[\"400\",\"450\",\"480\",\"500\",\"510\",\"520\"]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 } }, { "Id": 8, "Name": "社内確認中へ", "DisplayName": "社内確認中へ", "CurrentStatus": -1, "ChangedStatus": 520, "Description": "積算担当", "OnClick": "$p.ex.processScript($(this));", "Depts": [ 25 ], "View": { "Id": 0, "ColumnFilterHash": { "Status": "[\"400\",\"450\",\"480\",\"500\",\"510\",\"520\"]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 } }, { "Id": 9, "Name": "一部回答", "DisplayName": "一部回答", "CurrentStatus": -1, "ChangedStatus": 800, "Description": "積算担当", "OnClick": "$p.ex.processScript($(this));", "ValidateInputs": [ { "Id": 1, "ColumnName": "Description091", "Required": true } ], "Depts": [ 25 ], "View": { "Id": 0, "ColumnFilterHash": { "Status": "[\"400\",\"450\",\"480\",\"500\",\"510\",\"520\",\"800\"]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "Notifications": [ { "Type": 1, "Subject": "【デモ版】【営業積算】[ClassA]-[ClassB] [Class001]様 : 一部回答", "Address": "[ClassC]", "CcAddress": "[Class095]", "MediaType": "application/json", "Body": "【デモ版】\n営業積算より\n一部見積回答が届きました。([Num101]回目の回答)\n\n下記URLよりご確認ください。\n\n※このメールは送信専用です。\n 本メールに返信いただいても、内容は確認できませんのでご了承ください。\n お問い合わせは、営業積算窓口までご連絡ください。\n\n\n{Url}\n\n----------\n親番:[ClassA]\n子番:[ClassB]\n施主名:[Class001]\n----------\n\n見積回答:\n[Description091]\n\n別途費用・伝達事項:\n[Description092]\n\n----------\n\n■■■", "BeforeCondition": 0, "AfterCondition": 0, "Expression": 0, "Id": 1 } ] }, { "Id": 10, "Name": "見積回答", "DisplayName": "見積回答", "CurrentStatus": -1, "ChangedStatus": 810, "Description": "積算担当", "OnClick": "$p.ex.processScript($(this));", "ValidateInputs": [ { "Id": 1, "ColumnName": "Description091", "Required": true } ], "Depts": [ 25 ], "View": { "Id": 0, "ColumnFilterHash": { "Status": "[\"400\",\"450\",\"480\",\"500\",\"510\",\"520\",\"800\",\"810\"]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "Notifications": [ { "Type": 1, "Subject": "【デモ版】【営業積算】[ClassA]-[ClassB] [Class001]様 : 見積回答", "Address": "[ClassC]", "CcAddress": "[Class095]", "MediaType": "application/json", "Body": "【デモ版】\n営業積算より\n見積回答が届きました。([Num101]回目の回答)\n\n下記URLよりご確認ください。\n\n※このメールは送信専用です。\n 本メールに返信いただいても、内容は確認できませんのでご了承ください。\n お問い合わせは、営業積算窓口までご連絡ください。\n\n\n{Url}\n\n----------\n親番:[ClassA]\n子番:[ClassB]\n施主名:[Class001]\n----------\n\n見積回答:\n[Description091]\n\n別途費用・伝達事項:\n[Description092]\n\n----------\n\n■■■", "BeforeCondition": 0, "AfterCondition": 0, "Expression": 0, "Id": 1 } ] }, { "Id": 11, "Name": "完了", "DisplayName": "完了", "CurrentStatus": -1, "ChangedStatus": 900, "Description": "積算担当", "OnClick": "$p.ex.processScript($(this));", "Depts": [ 25 ], "View": { "Id": 0, "ColumnFilterHash": { "Status": "[\"800\",\"810\"]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 } }, { "Id": 12, "Name": "問い合わせ不要", "DisplayName": "問い合わせ不要", "CurrentStatus": -1, "ChangedStatus": 901, "Description": "積算担当", "OnClick": "$p.ex.processScript($(this));", "Depts": [ 25 ], "View": { "Id": 0, "ColumnFilterHash": { "Status": "[\"200\",\"400\",\"450\",\"480\",\"500\",\"510\",\"520\"]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "Notifications": [ { "Type": 1, "Subject": "【デモ版】【営業積算】[ClassA]-[ClassB] [Class001]様 : 問い合わせ不要", "Address": "[ClassC]", "CcAddress": "[Class052]", "MediaType": "application/json", "Body": "【デモ版】\n営業積算より\n本件について問い合わせ不要と判断いたしましたのでご連絡します。\n\n下記URLよりご確認ください。\n\n※このメールは送信専用です。\n 本メールに返信いただいても、内容は確認できませんのでご了承ください。\n お問い合わせは、営業積算窓口までご連絡ください。\n\n\n{Url}\n\n----------\n親番:[ClassA]\n子番:[ClassB]\n施主名:[Class001]\n----------\n\n■■■", "BeforeCondition": 0, "AfterCondition": 0, "Expression": 0, "Id": 1 } ] }, { "Id": 13, "Name": "依頼修正", "DisplayName": "依頼修正", "CurrentStatus": 200, "ChangedStatus": 100, "Description": "依頼者", "OnClick": "$p.ex.processScript($(this));", "View": { "Id": 0, "ColumnFilterHash": { "ClassC": "[\"Own\"]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 } }, { "Id": 14, "Name": "差戻し", "DisplayName": "差戻し", "CurrentStatus": -1, "ChangedStatus": 100, "Description": "積算担当", "OnClick": "$p.ex.processScript($(this));", "Depts": [ 25 ], "View": { "Id": 0, "ColumnFilterHash": { "Status": "[\"400\",\"450\",\"480\",\"500\",\"510\",\"520\"]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "Notifications": [ { "Type": 1, "Subject": "【デモ版】【営業積算】[ClassA]-[ClassB] [Class001]様 : 差戻し", "Address": "[ClassC]", "MediaType": "application/json", "Body": "【デモ版】\n営業積算より\n依頼内容の見直しをお願いしたく、差し戻しいたします。\n\nお手数ですが、下記URLより内容をご確認・修正のうえ、再度ご依頼ください。\n\n※このメールは送信専用です。\n 本メールに返信いただいても、内容は確認できませんのでご了承ください。\n お問い合わせは、営業積算窓口までご連絡ください。\n\n\n{Url}\n\n----------\n親番:[ClassA]\n子番:[ClassB]\n施主名:[Class001]\n----------\n\n■■■", "BeforeCondition": 0, "AfterCondition": 0, "Expression": 0, "Id": 1 } ] }, { "Id": 15, "Name": "依頼取消", "DisplayName": "依頼取消", "CurrentStatus": -1, "ChangedStatus": 920, "Description": "積算担当", "OnClick": "$p.ex.processScript($(this));", "Depts": [ 25 ], "View": { "Id": 0, "ColumnFilterHash": { "Status": "[\"400\",\"450\",\"480\",\"500\",\"510\",\"520\",\"910\"]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "Notifications": [ { "Type": 1, "Subject": "【デモ版】【営業積算】[ClassA]-[ClassB] [Class001]様 : 依頼取消", "Address": "[ClassC]", "CcAddress": "[Class052]", "MediaType": "application/json", "Body": "【デモ版】\n本件について、依頼者からの申し出により\n依頼取消となりましたのでご連絡します。\n\n下記URLよりご確認ください。\n\n\n{Url}\n\n----------\n親番:[ClassA]\n子番:[ClassB]\n施主名:[Class001]\n----------\n\n■■■", "BeforeCondition": 0, "AfterCondition": 0, "Expression": 0, "Id": 1 } ] }, { "Id": 16, "Name": "保留", "DisplayName": "保留", "CurrentStatus": -1, "ChangedStatus": 910, "Description": "積算担当", "OnClick": "$p.ex.processScript($(this));", "Depts": [ 25 ], "View": { "Id": 0, "ColumnFilterHash": { "Status": "[\"400\",\"450\",\"480\",\"500\",\"510\",\"520\"]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 } }, { "Id": 17, "Name": "保留解除", "DisplayName": "保留解除", "CurrentStatus": 910, "ChangedStatus": 500, "Description": "積算担当", "OnClick": "$p.ex.processScript($(this));", "Depts": [ 25 ], "View": { "Id": 0, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 } }, { "Id": 18, "Name": "遅延連絡", "DisplayName": "遅延連絡", "CurrentStatus": -1, "ChangedStatus": -1, "Description": "積算担当", "OnClick": "$p.ex.processScript($(this));", "Depts": [ 25 ], "View": { "Id": 0, "ColumnFilterHash": { "Status": "[\"400\",\"450\",\"480\",\"500\",\"510\",\"520\",\"800\"]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 }, "Notifications": [ { "Type": 1, "Subject": "【デモ版】【営業積算】[ClassA]-[ClassB] [Class001]様 : 遅延連絡", "Address": "[ClassC]", "CcAddress": "[Class085]", "MediaType": "application/json", "Body": "【デモ版】\n営業積算より\n見積回答遅延のご連絡です。\n\n下記URLよりご確認ください。\n\n※このメールは送信専用です。\n 本メールに返信いただいても、内容は確認できませんのでご了承ください。\n お問い合わせは、営業積算窓口までご連絡ください。\n\n\n{Url}\n\n----------\n親番:[ClassA]\n子番:[ClassB]\n施主名:[Class001]\n----------\n\n遅延理由:[Class086]\n返信予定日:[Date085]\n\n遅延連絡内容:\n[Description081]\n\n----------\n\n■■■", "BeforeCondition": 0, "AfterCondition": 0, "Expression": 0, "Id": 1 } ] }, { "Id": 19, "Name": "①物件基本情報へ戻る", "DisplayName": "①物件基本情報へ戻る", "CurrentStatus": -1, "ChangedStatus": -1, "Description": "制限なし", "OnClick": "$p.ex.processScript($(this));", "ActionType": 90, "View": { "Id": 0, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 } } ], "StatusControls": [ { "Id": 1, "Name": "依頼ロック", "Description": "新規依頼発行後、依頼内容の改変されないように項目をロックする", "Status": -1, "ColumnHash": { "ClassE": "ReadOnly", "ClassF": "ReadOnly", "ClassG": "ReadOnly", "ClassH": "ReadOnly", "ClassI": "ReadOnly", "Class007": "ReadOnly", "Class031": "ReadOnly", "Class032": "ReadOnly", "Class033": "ReadOnly", "Class034": "ReadOnly", "Class038": "ReadOnly", "Class039": "ReadOnly", "Class040": "ReadOnly", "Class045": "ReadOnly", "Class050": "ReadOnly", "Class052": "ReadOnly", "DateA": "ReadOnly", "DescriptionA": "ReadOnly", "DescriptionC": "ReadOnly", "Description031": "ReadOnly", "CheckA": "ReadOnly", "Check073": "ReadOnly", "Check074": "ReadOnly", "Attachments031": "ReadOnly" }, "View": { "Id": 0, "ColumnFilterHash": { "Status": "[\"200\",\"400\",\"450\",\"480\",\"500\",\"510\",\"520\",\"800\",\"810\",\"900\",\"901\",\"910\",\"920\"]" }, "ApiColumnKeyDisplayType": 0, "ApiColumnValueDisplayType": 0, "CalendarSiteId": 0, "ApiDataType": 0 } } ], "Styles": [ { "Title": "00_読み取り専用スタイル.css", "New": true, "Edit": true, "Body": "/*\n@config : next999.json\n@filename : 00_読み取り専用スタイル.css\n@title : 01_読み取り専用スタイル\n@name :\n@siteIds : 335101\n@siteTitles : ①物件基本情報\n@disabled: false\n*/\nlabel.error {\n pointer-events: none;\n z-index: 100;\n border-top: none !important;\n}\n\n.code-readonly {\n pointer-events: none;\n background-color: lightgrey;\n font-weight: bold;\n}\n\n.code-readonly2,\n.code-readonly2+button,\n.code-readonly2+div.ui-icon,\n.code-readonly3,\n.code-readonly3+button,\n.code-readonly3+div.ui-icon {\n font-weight: bold;\n\n &:active {\n pointer-events: none;\n }\n\n a:not(.ui-spinner-button) {\n pointer-events: auto;\n }\n\n}\n\n.code-readonly2 select,\n.code-readonly2 input,\n.code-readonly2 button.ui-multiselect,\n.code-readonly2 .control-markup,\n.code-readonly2 .ui-spinner,\nspan[data-readonly=\"1\"] {\n pointer-events: none;\n\n border: dashed 1px black;\n background-color: lightgray !important;\n color: black !important;\n\n .ui-spinner-input {\n border: none;\n }\n}\n\n.code-readonly3 select,\n.code-readonly3 input,\n.code-readonly3 button.ui-multiselect,\n.code-readonly3 .control-markup,\n.code-readonly3 .ui-spinner {\n pointer-events: none;\n\n border: dashed 1px black;\n\n .ui-spinner-input {\n border: none;\n }\n}\n\n.code-readonly2,\n.code-readonly3,\n.field-normal:has(span[data-readonly=\"1\"]),\n.field-wide:has(span[data-readonly=\"1\"]) {\n position: relative;\n\n &:hover::after {\n content: \"読取り専用です\";\n position: absolute;\n left: 120px;\n top: calc(100% - 9px);\n margin-top: 4px;\n background: #00000080;\n color: #fff;\n padding: 4px 10px;\n border-radius: 4px;\n font-size: 12px;\n font-weight: normal !important;\n pointer-events: none;\n z-index: 9999;\n white-space: nowrap;\n }\n}\n\n.code-required,\nselect[data-validate-required=\"1\"],\ninput[data-validate-required=\"1\"] {\n border: double 3px red !important;\n\n &+button.ui-multiselect {\n border: double 3px red !important;\n }\n\n}\n\n.field-normal:has(.code-required),\n.field-wide:has(.code-required),\n.field-normal:has(select[data-validate-required=\"1\"]),\n.field-wide:has(select[data-validate-required=\"1\"]),\n.field-normal:has(input[data-validate-required=\"1\"]),\n.field-wide:has(input[data-validate-required=\"1\"]) {\n position: relative;\n\n &:hover::after {\n content: \"入力必須です\";\n position: absolute;\n left: 120px;\n top: calc(100% - 9px);\n margin-top: 4px;\n background: #ff000080;\n color: #fff;\n padding: 4px 10px;\n border-radius: 4px;\n font-size: 12px;\n font-weight: normal !important;\n pointer-events: none;\n z-index: 9999;\n white-space: nowrap;\n }\n}\n\n.error {\n border: double 3px red !important;\n}", "Id": 1 }, { "Title": "01_共通スタイル.css", "New": true, "Edit": true, "Body": "/*\n@config :\n@filename : ${psFileBasename}\n@title : 01_共通スタイル\n@name\n@siteIds :\n@siteTitles : 物件基本情報\n@disabled: false\n*/\n\n/*見出しサイズ*/\n.field-section {\n font-size: 1.5em !important;\n font-weight: bold !important;\n height: auto;\n}\n\n/*項目の後ろの行間を少し狭める*/\n.field-normal {\n height: 35px;\n}\n\n.field-wide {\n min-height: 35px;\n padding: 0 10px 5px 0;\n}\n\n/*コメントのある項目の高さだけ少し広げる*/\ndiv:has(.commentAdd).field-normal {\n height: 50px;\n}\n\n.dateA_alert {\n background-color: red !important;\n color: white !important;\n}\n\n/*「営業積算」タブ(_Tab-2/FieldSetTab2):既定非表示。営業積算課(Dept25)のみ01_基本スクリプト.jsが\n bodyへshow-sekisan-tabクラスを付与し表示化する(01_基本スクリプト.js側の判定と対)*/\n#EditorTabs li[aria-controls=\"FieldSetTab2\"] {\n display: none !important;\n}\n\n#FieldSetTab2 {\n display: none !important;\n}\n\nbody.show-sekisan-tab #EditorTabs li[aria-controls=\"FieldSetTab2\"] {\n display: list-item !important;\n}\n\n/*このタブが「現在アクティブなタブ」の時のみ強制表示。jQuery UI Tabsは非アクティブ時に\n aria-hidden=\"true\"を付与するため、それ以外(=アクティブ時)にだけ上書きし、\n 他タブ表示中は非表示ルール(上のdisplay:none !important)を効かせたままにする。\n ここに:not([aria-hidden=\"true\"])を付けないと、権限を満たすユーザーが他タブを開いていても\n 本タブの中身が常時描画され続けてしまう(実際に発生していた不具合)*/\nbody.show-sekisan-tab #FieldSetTab2:not([aria-hidden=\"true\"]) {\n display: block !important;\n}\n\n/*「積算発注」タブ(_Tab-3/FieldSetTab3):既定非表示。dept25/26/28/66/36所属者またはuserId 913/987/1153のみ\n bodyへshow-sekisan-hachu-tabクラスを付与し表示化する(01_基本スクリプト.js側の判定と対)*/\n#EditorTabs li[aria-controls=\"FieldSetTab3\"] {\n display: none !important;\n}\n\n#FieldSetTab3 {\n display: none !important;\n}\n\nbody.show-sekisan-hachu-tab #EditorTabs li[aria-controls=\"FieldSetTab3\"] {\n display: list-item !important;\n}\n\n/*FieldSetTab2と同じ理由でaria-hidden除外を追加(他タブ表示中の常時描画を防ぐ)*/\nbody.show-sekisan-hachu-tab #FieldSetTab3:not([aria-hidden=\"true\"]) {\n display: block !important;\n}", "Id": 2 }, { "Title": "3_04_質疑回答テーブル.css", "New": true, "Edit": true, "Body": "/*\n@config :\n@filename : 04_質疑回答テーブル.css\n@title : 04_質疑回答テーブル\n@name :\n@siteIds :\n@siteTitles : 問合せ内容管理\n@disabled: false\n*/\n\n#messageTable {\n width: 98%;\n margin: 8px;\n border-collapse: separate !important;\n}\n\n.radius-table {\n border-radius: 10px !important;\n border-spacing: 0;\n border: none;\n border-left: 1px solid #999;\n border-top: 1px solid #999;\n}\n\n.radius-table tr>* {\n padding: 5px 10px;\n border: none;\n border-right: 1px solid #999;\n border-bottom: 1px solid #999;\n}\n\n.radius-table tr:first-child>*:first-child {\n border-radius: 10px 0 0 0;\n}\n\n.radius-table tr:first-child>*:last-child {\n border-radius: 0 10px 0 0;\n}\n\n.radius-table tr:last-child>*:first-child {\n border-radius: 0 0 0 10px;\n}\n\n.radius-table tr:last-child>*:last-child {\n border-radius: 0 0 10px 0;\n}\n\n.Question>td {\n background-color: coral;\n vertical-align: middle;\n}\n\n.Question\\.Disabled>td,\n.Answer\\.Disabled>td {\n background-color: grey !important;\n}\n\n.Answer>td {\n background-color: yellow;\n vertical-align: middle;\n\n}\n\n.shitsugi_type {\n font-weight: bold;\n font-size: 1.5em;\n}\n\n.shitsugi_userName {\n text-align: center;\n width: 150px;\n font-size: 1.2em;\n}\n\n.shitsugi_messageTime {\n text-align: right;\n font-size: 1.2em;\n}\n\n.shitsugi_messageBody {\n background-color: white !important;\n}\n\n.shitsugi_deleteCheck {\n background-color: white !important;\n text-align: center;\n width: 80px;\n}\n\n.shitsugi_preWrap {\n white-space: pre-wrap;\n text-overflow: ellipsis;\n break-inside: avoid;\n}\n", "Id": 3 } ], "Scripts": [ { "Title": "01_基本スクリプト.js", "New": true, "Edit": true, "Body": "/*\n@config :\n@filename : ${psFileBasename}\n@title : 01_基本スクリプト\n@name :\n@siteIds :\n@siteTitles : 問合せ内容管理\n@disabled: false\n*/\n\nlet pageLoading = 0;\n\n//組織によって質疑応答の操作可否を分岐するフラグ(DeptId 25 = 営業積算)\nlet eSekisanFlag = false;\nlet eSekisanDeptId = '25';\n\n//dept25(営業積算)所属者のUserId→氏名解決マップ(ログ文字列生成・タブ間ミラー表示用のみ)。\n//ServerScript「Dept25所属者取得スクリプト」が画面表示前に取得済みのDept25Members(Hidden項目)から読み込む。\n//選択肢自体はChoicesText側でUsersマスタからDeptId=25指定で動的取得している\nlet dept25UserNames = $('#Dept25Members').length > 0 ? JSON.parse($('#Dept25Members').val()) : {};\n//UserIdを氏名に解決する。マップに無い値(旧レコードの氏名文字列そのまま等)はそのまま返す\nfunction resolveUserName(val) {\n if (!val) return val;\n return dept25UserNames[val] || val;\n}\n\n//問い合わせ不要理由テンプレ(SiteId 504319)のResultId→内容(DescriptionA)マップ。\n//ServerScript「問い合わせ不要理由テンプレ取得スクリプト」が画面表示前に取得済みのInquiryUnneededReasonMap\n//(Hidden項目)から読み込む。Class089(不要理由)変更時にDescription091(見積回答)へ同期反映するために使う\nlet inquiryUnneededReasonMap = $('#InquiryUnneededReasonMap').length > 0 ? JSON.parse($('#InquiryUnneededReasonMap').val()) : {};\n\n//必須項目未入力の強調表示クラス(code-required)を付け外しする。\n//Markdown型(Description等)は本体textarea(id=col)がdisplay:noneで、代わりに\n//ビューア要素(id=\"col.viewer\")が表示されているため、実体だけにクラスを付けても見た目に反映されない。\n//両方へ付け外しする(通常のinput/select型はビューア要素が存在しないため実害なし)。\n$p.ex.toggleRequiredMark = function (col, isMissing) {\n $('#Results_' + col).toggleClass('code-required', isMissing);\n $('[id=\"Results_' + col + '.viewer\"]').toggleClass('code-required', isMissing);\n}\n\n//新規作成画面の「作成」ボタン(#CreateCommand)の表示文言を「一時保存」に変更する。\n//アイコン用span(ui-button-icon/ui-button-icon-space)はそのまま残し、末尾のテキストノードだけ書き換える\n$p.ex.changeCreateButtonLabel = function () {\n let $btn = $('#CreateCommand');\n let textNode = $btn.contents().filter(function () {\n return this.nodeType === 3; //テキストノードのみ対象\n }).last();\n\n if (textNode.length) {\n textNode[0].nodeValue = '一時保存';\n }\n}\n\n//作成ボタン押下後の既存レコードでStatus=100(積算への依頼が未完了)の間、依頼完了を促すメッセージを表示する\n$p.ex.showPendingRequestReminder = function () {\n let status = $('#Results_Status').val();\n if (status !== '100') return;\n $p.ex.setMyMessage('new-status-yellow', '現在、積算への依頼が完了しておりません。依頼を完了する場合は、「積算へ依頼」ボタンを押してください。');\n}\n\n//積算発注タブ(_Tab-3/FieldSetTab3)表示対象の組織コード:25(営業積算),26(積算発注管理課),28(東京工務課),66(君津住宅工務課),36(愛知工務課)\nlet sekisanHachuViewDeptIds = ['25', '26', '28', '66', '36'];\n//積算発注タブ(_Tab-3/FieldSetTab3)表示対象の個別ユーザーコード(上記部署に属さなくても表示許可する例外ユーザー):\n//913(青地渉),987(中川真悟),1153(長谷川等志)\nlet sekisanHachuViewUserIds = ['913', '987', '1153'];\n//ブランドコード(Results_Class004の値):109101=nexthouse, 268122=nexthouse VALUE\n//マトリックスの場合のnexthouseシリーズ(Class040)必須判定でのみ使用\nlet nexthouseBrandCodes = ['109101', '268122'];\n\n//----------------------------------------------------------------------\n//初期処理\nwindow.addEventListener('load', function () {\n if (pageLoading == 0) {\n console.log('Window load Event');\n $p.ex.onLoad();\n }\n});\n\n$p.events.on_editor_load = function () {\n if (pageLoading == 0) {\n console.log('on Editor Load');\n $p.ex.onLoad();\n }\n}\n\n//----------------------------------------------------------------------\n$p.ex.onLoad = function () {\n //ロード開始\n pageLoading = 1;\n\n //初期処理\n $p.ex.init();\n}\n\n//初期処理\n$p.ex.init = function () {\n console.log('initialize...');\n\n //営業積算(DeptId 25)かどうかを判定\n eSekisanFlag = ($p.deptId() == eSekisanDeptId);\n\n //「営業積算」タブ(_Tab-2/FieldSetTab2)は営業積算(Dept25)のみ閲覧・編集可。\n //既定は01_共通スタイル.cssで非表示、Dept25のみここでbodyへクラス付与し表示化する\n if (eSekisanFlag) {\n $('body').addClass('show-sekisan-tab');\n }\n\n //積算発注タブ(_Tab-3/FieldSetTab3)表示対象:dept25(営業積算),26(積算発注),28,66,36(各エリア工務)またはuserId 913,987,1153\n //(sekisanHachuViewDeptIds/sekisanHachuViewUserIdsはファイル先頭のグローバル変数宣言を参照)\n let deptIdStr = $p.deptId().toString();\n let userIdStr = $p.userId().toString();\n\n if (sekisanHachuViewDeptIds.includes(deptIdStr) || sekisanHachuViewUserIds.includes(userIdStr)) {\n $('body').addClass('show-sekisan-hachu-tab');\n }\n\n //新規作成時のみ処理\n if ($p.action() == 'new') {\n //①物件基本情報からのリンク経由でない場合(ClassZ空欄)は警告表示(保存自体はbefore_validateでブロック)\n if (!$('#Results_ClassZ').val()) {\n $p.ex.setMyMessage('new-status-red', '①物件基本情報から新規依頼を作成してください');\n }\n\n //祝日計算\n $p.getHolidayTable();\n\n //「作成」ボタンの表示文言を「一時保存」に変更(アイコンはそのまま)\n $p.ex.changeCreateButtonLabel();\n } else {\n //作成ボタン押下後、Status=100(積算への依頼が未完了)の間は依頼完了を促すメッセージを常時表示\n $p.ex.showPendingRequestReminder();\n\n //スタートアップメッセージ表示\n //$p.ex.startupMessage();\n $p.setSubNumber();\n\n //質疑応答送信ボタン生成\n $p.ex.messageSaveButton();\n\n //受付ボタン生成\n $p.ex.receiptButton();\n\n //外部見積待ちへボタン生成\n $p.ex.externalEstimateWaitButton();\n\n //社内確認中へ・差戻しボタン生成\n $p.ex.statusRowButtons();\n\n //遅延連絡ボタン生成\n $p.ex.delayNoticeButton();\n\n //問い合わせ不要ボタン生成(一部回答ボタンより先に生成し、一部回答をその直下に配置する)\n $p.ex.inquiryUnnecessaryButton();\n\n //一部回答ボタン生成(見積回答ボタンより先に生成し、見積回答をその直下に配置する)\n $p.ex.partialAnswerButton();\n\n //見積回答ボタン生成\n $p.ex.estimateReplyButton();\n\n //見積回答ファイル(Attachments101)一括DLボタン生成(Description062の下に配置)\n $p.ex.estimateAttachmentsDLButton();\n\n //「①物件基本情報へ戻る」ボタンをコマンド欄の一番左に移動\n $p.ex.moveBackButtonToFirst();\n\n //質疑応答メッセージ履歴表示\n $p.ex.messageHistory();\n }\n\n //見積回答結果欄外の固定文(多色使いルールURL・保証関連の免責文)\n $('#Results_Description062Field').after(\n '
' +\n '<別途>多色使いルール・割増価格一覧 ※必要な場合
' +\n 'https://nextgroup.notepm.jp/page/25faf74577
' +\n '
' +\n '※営業積算では納まり、瑕疵含む保証関連は確認、検討しておりません' +\n '
'\n );\n\n //添付ファイル項目欄調整\n let attachColumns = $('.control-attachments');\n $.each(attachColumns, function (index, value) {\n let attach = value.dataset.name;\n attachmentComments(attach);\n attachFileCheckbox(attach);\n })\n\n //質疑ファイル・回答ファイルのファイル名一覧表示はいったんコメントアウト(標準UIで既にファイル名が\n //表示されているため。2026-08-11)\n //$p.ex.showAttachmentFileNames('Attachments071');\n //$p.ex.showAttachmentFileNames('Attachments072');\n\n //----------------------------------------------------------------------\n //Results_ClassG(現在の進捗)変更時に項目の表示/非表示を切替\n //ClassGは「新規依頼」プロセス実行後に読取専用化されるため、控え項目ClassT(現在の進捗(控え))へ常に同期しておき、\n //表示切替の判定はClassTを参照する(読取専用化後は$('#Results_ClassG').val()が空になるため)\n $('input[name=\"Results_ClassG\"]').on('change', function () {\n $p.toggleClassGFields($(this).val());\n $p.set($('#Results_ClassT'), $(this).val());\n });\n $p.toggleClassGFields($('#Results_ClassT').val());\n\n //----------------------------------------------------------------------\n //Results_Class007(問合せ種別)変更時にマトリックス以外/マトリックスの入力欄表示を切替\n $('input[name=\"Results_Class007\"]').on('change', function () {\n $p.ex.toggleInquiryTypeFields($(this).val());\n });\n $p.ex.toggleInquiryTypeFields($('#Results_Class007').val());\n\n //----------------------------------------------------------------------\n //Results_Class055(不備・追加)欄は項目削除に伴い不要化(2026-08-01コメントアウト)\n /*\n $('input[name=\"Results_Class055\"]').on('change', function () {\n $p.toggleClass055Fields($(this).val());\n });\n $p.toggleClass055Fields($('#Results_Class055').val());\n */\n\n //アップ希望日チェックイベント登録\n $p.on('change', 'DateA', function () {\n $p.clearMessage();\n $p.upDateCheck();\n });\n\n //----------------------------------------------------------------------\n //Status(状況)とClass062(状況)の値を相互に同期\n $('#Results_Status').on('change', function () {\n $p.ex.syncStatusAndClass062('Status');\n });\n $('#Results_Class062').on('change', function () {\n $p.ex.syncStatusAndClass062('Class062');\n });\n\n //----------------------------------------------------------------------\n //Class089(不要理由)選択時、対応するテンプレ内容(DescriptionA)をDescription091(見積回答)へ同期的に反映する\n //(旧SiteSettings.LinksによるAutoPostBack Lookupは非同期のため、選択直後にプロセスボタンを押すと\n // 反映前にexecProcessが送信されてしまう不具合があった。2026-08-23、クライアント側同期処理へ変更)\n $p.on('change', 'Class089', function () {\n let resultId = $('#Results_Class089').val();\n if (resultId && inquiryUnneededReasonMap[resultId] !== undefined) {\n $p.set($('#Results_Description091'), inquiryUnneededReasonMap[resultId]);\n }\n });\n\n //code-readonly2(読取り専用)が設定されている全フィールドをTab移動対象から除外する\n $p.applyReadonlyTabindex();\n}\n\n//----------------------------------------------------------------------\n//code-readonly2(読取り専用)が設定されている全フィールドをTab移動対象から除外する。\n//pointer-events:noneはマウス操作のみ無効化し、Tabキーでのフォーカス移動・キーボード操作での\n//選択変更は防げないため、tabindex=\"-1\"を併用する(①物件基本情報サイトと同じ方式)。\n//StatusControls「依頼ロック」によるReadOnly化(ExtendedFieldCssとは別のPleasanter標準機構)は\n//DOM上の表現が未確認のため対象外。ExtendedFieldCss: \"code-readonly2\"の静的設定項目のみ対応。\n$p.applyReadonlyTabindex = function () {\n $('select, input, textarea').each(function () {\n let $el = $(this);\n if ($el.closest('.code-readonly2').length) {\n $el.attr('tabindex', '-1');\n } else if ($el.attr('tabindex') === '-1') {\n $el.removeAttr('tabindex');\n }\n });\n}\n\n//Status変更時はClass062へ、Class062変更時はStatusへ値をコピーする(無限ループ防止のため値が異なる場合のみ更新)\n$p.ex.syncStatusAndClass062 = function (changedField) {\n let statusVal = $('#Results_Status').val();\n let class062Val = $('#Results_Class062').val();\n\n if (changedField === 'Status') {\n if (class062Val !== statusVal) {\n $p.set($('#Results_Class062'), statusVal);\n }\n } else {\n if (statusVal !== class062Val) {\n $p.set($('#Results_Status'), class062Val);\n }\n }\n}\n\n$p.setSubNumber = function () {\n // サブ番号の設定ロジック\n let classB = $('#Results_ClassB').val();\n let classX = $('#Results_ClassX').val();\n\n let subNumber = classX.split('-')[1]; // 管理番号を「-」で分割して、子番を取得\n if (subNumber && subNumber !== classB) {\n // サブ番号を設定\n $p.set($('#Results_ClassB'), subNumber);\n }\n};\n\n//Results_ClassG(現在の進捗)変更時に項目の表示/非表示を切替\n$p.toggleClassGFields = function (value) {\n if (value == '1') {\n //表示\n $('#Results_ClassHField').show();\n $('#Results_ClassIField').show();\n $('#Results_DescriptionAField').show();\n $('#Results_Class088Field').show();\n $('#Results_Check073Field').show();\n $('#Results_Check074Field').show();\n } else {\n //非表示\n $('#Results_ClassHField').hide();\n $('#Results_ClassIField').hide();\n $('#Results_DescriptionAField').hide();\n $('#Results_Class088Field').hide();\n $('#Results_Check073Field').hide();\n $('#Results_Check074Field').hide();\n }\n}\n\n//ClassG(現在の進捗)が「1:承認図後・着工中」の場合の必須項目チェック\n//(プロセス実行後はClassG/H/Iが読取専用化されるため、実行前のここでのみチェック可能)\n//4_04_プロセス処理スクリプト.js「積算へ依頼」ケースから呼ばれる\n$p.ex.checkClassGRequiredFields = function () {\n let classGVal = $('#Results_ClassG').val();\n let targetCols = ['ClassH', 'ClassI', 'Class088', 'Check073', 'Check074'];\n\n if (classGVal != '1') {\n //対象外の場合は強調表示だけクリアする\n targetCols.forEach(function (col) { $p.ex.toggleRequiredMark(col, false); });\n return true;\n }\n\n let emptyLabels = [];\n let missingCols = [];\n\n if (!$('#Results_ClassH').val()) { emptyLabels.push('現場の進捗'); missingCols.push('ClassH'); }\n if (!$('#Results_ClassI').val()) { emptyLabels.push('必要な見積金額'); missingCols.push('ClassI'); }\n if (!$('#Results_Class088').val()) { emptyLabels.push('担当監督'); missingCols.push('Class088'); }\n if ($('#Results_Check073').val() != 'checked') { emptyLabels.push('稟議ではないことを確認済み'); missingCols.push('Check073'); }\n if ($('#Results_Check074').val() != 'checked') { emptyLabels.push('承認図後追加変更契約 定義書①~④以外である'); missingCols.push('Check074'); }\n\n targetCols.forEach(function (col) { $p.ex.toggleRequiredMark(col, missingCols.includes(col)); });\n\n if (emptyLabels.length > 0) {\n window.alert(emptyLabels.join('、') + ' は必須項目です。入力してください。');\n return false;\n }\n return true;\n}\n\n//----------------------------------------------------------------------\n//Results_Class007(問合せ種別)の値に応じて、マトリックス以外/マトリックスそれぞれの入力欄を表示/非表示\n//「マトリックス以外」→Class031-034,Description031,Class045,Class050を表示\n//「マトリックス」→Class038,Class039,Class040を表示\n//未選択の場合は両方非表示\n$p.ex.otherTypeFieldNames = ['Class031', 'Class032', 'Class033', 'Class034', 'Description031', 'Class045', 'Class050'];\n$p.ex.matrixTypeFieldNames = ['Class038', 'Class039', 'Class040'];\n$p.ex.toggleInquiryTypeFields = function (value) {\n if (value == 'マトリックス以外') {\n $p.ex.otherTypeFieldNames.forEach(function (c) { $('#Results_' + c + 'Field').show(); });\n $p.ex.matrixTypeFieldNames.forEach(function (c) { $('#Results_' + c + 'Field').hide(); });\n //matrixTypeFieldNames(Class038-040)を内包するセクション(Id17)のコンテナごと非表示にする\n $('#SectionFields17Container').hide();\n } else if (value == 'マトリックス') {\n $p.ex.otherTypeFieldNames.forEach(function (c) { $('#Results_' + c + 'Field').hide(); });\n $p.ex.matrixTypeFieldNames.forEach(function (c) { $('#Results_' + c + 'Field').show(); });\n $('#SectionFields17Container').show();\n } else {\n $p.ex.otherTypeFieldNames.concat($p.ex.matrixTypeFieldNames).forEach(function (c) { $('#Results_' + c + 'Field').hide(); });\n $('#SectionFields17Container').hide();\n }\n}\n\n//保存時、問合せ種別で選択されなかった側の項目に入力が残っていた場合はクリアする\n$p.ex.clearInquiryTypeFields = function () {\n let type = $('#Results_Class007').val();\n let clearTargets;\n if (type == 'マトリックス以外') {\n clearTargets = $p.ex.matrixTypeFieldNames;\n } else if (type == 'マトリックス') {\n clearTargets = $p.ex.otherTypeFieldNames;\n } else {\n clearTargets = $p.ex.otherTypeFieldNames.concat($p.ex.matrixTypeFieldNames);\n }\n clearTargets.forEach(function (c) {\n let $el = $('#Results_' + c);\n if ($el.val()) $p.set($el, '');\n });\n}\n\n//問合せ種別に応じた必須項目チェック(プロセス「積算へ依頼」実行前にのみ呼ばれる)\n//マトリックスの場合のnexthouseシリーズ(Class040)は、ブランド(Class004)が\n//109101(nexthouse)または268122(nexthouse VALUE)のときのみ必須とする\n$p.ex.checkInquiryTypeRequiredFields = function () {\n let type = $('#Results_Class007').val();\n let emptyLabels = [];\n let missingCols = [];\n\n if (!type) {\n emptyLabels.push('問合せ種別');\n } else if (type == 'マトリックス以外') {\n if (!$('#Results_Class031').val()) { emptyLabels.push('メーカー'); missingCols.push('Class031'); }\n if (!$('#Results_Class032').val()) { emptyLabels.push('商品名'); missingCols.push('Class032'); }\n if (!$('#Results_Class033').val()) { emptyLabels.push('品番'); missingCols.push('Class033'); }\n if (!$('#Results_Class034').val()) { emptyLabels.push('施工範囲・箇所'); missingCols.push('Class034'); }\n } else if (type == 'マトリックス') {\n if (!$('#Results_Class038').val()) { emptyLabels.push('積算Ver.'); missingCols.push('Class038'); }\n if (!$('#Results_Class039').val()) { emptyLabels.push('マトリックスサイズ'); missingCols.push('Class039'); }\n\n let class004 = $('#Results_Class004').val();\n if (nexthouseBrandCodes.includes(String(class004)) && !$('#Results_Class040').val()) {\n emptyLabels.push('nexthouseシリーズ');\n missingCols.push('Class040');\n }\n }\n\n //チェック対象となりうる項目は毎回全てクリアしてから、未入力だった項目にのみ強調表示クラスを付け直す\n ['Class031', 'Class032', 'Class033', 'Class034', 'Class038', 'Class039', 'Class040'].forEach(function (col) {\n $p.ex.toggleRequiredMark(col, missingCols.includes(col));\n });\n\n if (emptyLabels.length > 0) {\n window.alert(emptyLabels.join('、') + ' は必須項目です。入力してください。');\n return false;\n }\n return true;\n}\n\n//Class040(nexthouseシリーズ)のラジオボタン選択を解除する\n$p.ex.clearClass040 = function () {\n $('input[name=\"Results_Class040\"]').prop('checked', false);\n $p.set($('#Results_Class040'), '');\n}\n\n//Results_Class055(不備・追加)欄は項目削除に伴い不要化(2026-08-01コメントアウト)\n/*\n$p.toggleClass055Fields = function (value) {\n if (value == '1') {\n //表示\n $('#Results_Class056Field').show();\n $('#Results_Attachments055Field').show();\n $('#Results_Description055Field').show();\n $('#Attachments055_dlButton1').show(); //添付ファイルのダウンロードボタンを表示\n $('#Attachments055_dlButton2').show(); //添付ファイルのダウンロードボタンを表示\n } else {\n //非表示\n $('#Results_Class056Field').hide();\n $('#Results_Attachments055Field').hide();\n $('#Results_Description055Field').hide();\n $('#Attachments055_dlButton1').hide(); //添付ファイルのダウンロードボタンを非表示\n $('#Attachments055_dlButton2').hide(); //添付ファイルのダウンロードボタンを非表示\n }\n}\n*/\n\n//入力チェック前処理\n$p.events.before_validate = function (args) {\n\n //ClassZ(①物件基本情報からのリンク元ID)が空欄の場合、新規作成をブロックする\n if (!$p.ex.checkClassZRequired()) {\n return false;\n }\n\n //問合せ種別で選択されなかった側の項目をクリア\n $p.ex.clearInquiryTypeFields();\n\n //依頼内容マージ\n $p.mergeMainMessage();\n\n //算出対応ログの保存\n $p.saveCalculateLog();\n\n //遅延連絡ログ\n $p.saveReasonLog();\n\n //見積回答・別途費用の統合と転記\n $p.mergeEstimateResult();\n\n //営業積算タブ→問い合わせ情報タブへの転記(同一レコード内)\n $p.syncSekisanTabToGeneralTab();\n\n //依頼者(ClassC)+担当者・CC一覧(Class153)をマージしてClassY(依頼者・担当者・CC一覧)へ保存\n $p.mergeClassY();\n\n //ClassG(現在の進捗)の必須チェックは「新規依頼」プロセス実行前処理(04_プロセス処理スクリプト.js)へ移設。\n //新規依頼プロセス実行後はClassG/ClassH/ClassIが読取専用化され$('#Results_ClassH').val()等が取得できなくなるため、\n //通常保存時(本関数)では行わない\n\n //DescriptionC(依頼内容)はHide化しmergeMainMessageによる自動集約専用項目になったため、\n //ユーザー入力前提の必須チェック(checkDescriptionCRequired)は廃止\n}\n\n//入力チェック後処理\n$p.events.after_validate = function (args) {\n\n}\n\n//画面更新後\n$p.events.after_set_Update = function (args) {\n //初期処理\n $p.ex.init();\n}\n\n//①物件基本情報から新規依頼作成後、遷移元(①)へ戻らず作成した②自身のレコードに留まる設定は\n//ClassZ(①物件基本情報からのリンク元ID)のChoicesText側でNotReturnParentRecordオプションとして\n//宣言的に設定する(Pleasanter標準機能。スクリプト側での対応は不要)\n//参照: https://pleasanter.org/ja/manual/table-management-choices-text-link\n\n\n//アップ希望日時の確認と警告\n$p.upDateCheck = function () {\n if ($('#Results_DateA').val() != '') {\n let dateA = new Date($('#Results_DateA').val());\n let dateJ = new Date($('#Results_DateJ').val());\n\n //もしdateJが空の場合 $p.getHolidayTable() を再度実行して、dateJを取得する\n if ($('#Results_DateJ').val() == '') {\n $p.getHolidayTable();\n dateJ = new Date($('#Results_DateJ').val());\n }\n\n //アップ希望日が期限日より手前の場合\n if (dateA.getTime() < dateJ.getTime()) {\n $('#Results_DateA').addClass('dateA_alert');\n $p.ex.setMyMessage('new-status-red', '期日は選択可最短日以降を選択してください。');\n\n return false;\n } else {\n $('#Results_DateA').removeClass('dateA_alert');\n\n return true;\n }\n }\n}\n\n//祝日判定テーブルの取得\n//ServerScript「祝日リスト取得スクリプト」が画面表示前に取得済みのHolidaysList(Hidden項目)から読み込む\n$p.getHolidayTable = function () {\n let holidays = $('#HolidaysList').length > 0 ? JSON.parse($('#HolidaysList').val()) : [];\n\n let limitDate = new Date();\n limitDate.setHours(0);\n limitDate.setMinutes(0);\n limitDate.setSeconds(0);\n\n //土日祝日を除く5日後をカウント\n let count = 0;\n while (count < 5) {\n limitDate.setDate(limitDate.getDate() + 1);\n let limitDateStr = limitDate.getFullYear() + '/' + (limitDate.getMonth() + 1).toString().padStart(2, '0') + '/' + limitDate.getDate().toString().padStart(2, '0');\n if (!(limitDate.getDay() == 0) && !(limitDate.getDay() == 6) && !(holidays.includes(limitDateStr))) {\n count++;\n }\n }\n\n let limitDateStr = limitDate.getFullYear() + '/' + (limitDate.getMonth() + 1).toString().padStart(2, '0') + '/' + limitDate.getDate().toString().padStart(2, '0');\n $p.set($('#Results_DateJ'), limitDateStr);\n}\n\n\n//----------------------------------------------------------------------\n//依頼内容マージ:OK6/21\n//問合せ種別(Class007)により、DescriptionCへマージする項目セットを切り替える\n//0:マトリックス以外→Class031(メーカー)、Class032(商品名)、Class033(品番)、Class034(施工範囲・箇所)、\n// Description031(依頼内容補足)、Class045(標準仕様)、Class050(前回の管理番号)\n//1:マトリックス→Class038(積算Ver.)、Class039(マトリックスサイズ)、Class040(nexthouseシリーズ)\n$p.mergeMainMessage = function (args) {\n //StatusControls「依頼ロック」(Status=100以外)が適用されるとマージ元(Class031等)もDescriptionC自身も\n //ReadOnly化され、ReadOnly化された項目は$('#Results_XXX').val()で値を正しく取得できない\n //(Pleasanter標準仕様。詳細はapplyReadonlyTabindexの注記を参照)。ロック中に再マージを実行すると\n //取得できない値のせいでDescriptionCが空文字で上書きされてしまうため、Status=100(依頼ロック前)の\n //間のみ実行し、ロック後は既存の値をそのまま保持する\n let currentStatus = $('#Results_Status').val();\n if (currentStatus && currentStatus !== '100') {\n return;\n }\n\n //対象項目(種別自体の変更含む)の変更があった場合のみ処理する\n let includeList = ['Results_Class007', 'Results_Class031', 'Results_Class032', 'Results_Class033', 'Results_Class034', 'Results_Description031', 'Results_Class045', 'Results_Class050', 'Results_Class038', 'Results_Class039', 'Results_Class040'];\n let checkFlug = false;\n $.each($p.data.MainForm, function (index, val) {\n if (index.startsWith('Results')) {\n if (includeList.includes(index)) {\n // 処理内容\n checkFlug = true;\n }\n }\n });\n\n if (checkFlug) {\n let type = $('#Results_Class007').val();\n let mergeStr = []; //マージする文字列を格納する配列\n\n if (type == 'マトリックス') {\n mergeStr.push($('#Results_Class038').val()); //Class038(積算Ver.)の値を配列に格納\n mergeStr.push($('#Results_Class039').val()); //Class039(マトリックスサイズ)の値を配列に格納\n mergeStr.push($('#Results_Class040').val()); //Class040(nexthouseシリーズ)の値を配列に格納\n } else {\n mergeStr.push($('#Results_Class031').val()); //Class031(メーカー)の値を配列に格納\n mergeStr.push($('#Results_Class032').val()); //Class032(商品名)の値を配列に格納\n mergeStr.push($('#Results_Class033').val()); //Class033(品番)の値を配列に格納\n mergeStr.push($('#Results_Class034').val()); //Class034(施工範囲・箇所)の値を配列に格納\n mergeStr.push($('#Results_Description031').val()); //Description031(依頼内容補足)の値を配列に格納\n mergeStr.push($('#Results_Class045').val()); //Class045(標準仕様)の値を配列に格納\n mergeStr.push($('#Results_Class050').val()); //Class050(前回の管理番号)の値を配列に格納\n }\n\n //空欄(未入力)の項目を除外する\n mergeStr = mergeStr.filter(function (val) {\n return val && val.trim() !== '';\n });\n\n //改行で結合して、DescriptionCに格納\n $p.set($('#Results_DescriptionC'), mergeStr.join('\\n'));\n }\n}\n\n\n//----------------------------------------------------------------------\n//遅延連絡ログ\n//Class086遅延理由、Class087遅延連絡者\n//Date084遅延連絡日、Date085返信予定日\n//Description081遅延連絡内容\n$p.saveReasonLog = function () {\n //対象項目の変更があった場合のみログを保存する\n let includeList = ['Results_Class086', 'Results_Class087', 'Results_Date084', 'Results_Date085', 'Results_Description081'];\n let checkFlug = false;\n $.each($p.data.MainForm, function (index, val) {\n if (index.startsWith('Results')) {\n if (includeList.includes(index)) {\n // 処理内容\n checkFlug = true;\n }\n }\n });\n\n if (checkFlug) {\n let logStr = [];\n let reasonText = $('#Results_Class086 option:selected').text(); //遅延理由の表示テキストを取得\n logStr.push('遅延理由:' + reasonText); //Class086の表示文字列を配列に格納\n logStr.push('遅延連絡者:' + resolveUserName($('#Results_Class087').val())); //Class087の値を氏名に解決して配列に格納\n logStr.push('遅延連絡日:' + $('#Results_Date084').val()); //Date084の値を配列に格納\n logStr.push('返信予定日:' + $('#Results_Date085').val()); //Date085の値を配列に格納\n logStr.push('遅延連絡内容:' + '\\n' + $('#Results_Description081').val()); //Description081の値を配列に格納\n\n let orgLog = $('#Results_Description083').val(); //Description083の既存の値を取得\n //新しいログを先頭(上)にして、既存のログがある場合はその下に結合。ない場合は新しいログのみ\n let saveLog = orgLog ? logStr.join('\\n') + '\\n----------------------\\n' + orgLog : logStr.join('\\n');\n $p.set($('#Results_Description083'), saveLog); //Description083に保存\n }\n\n}\n\n//算出対応ログ\n$p.saveCalculateLog = function () {\n //対象項目の変更があった場合のみログを保存する\n let includeList = ['Results_Class101', 'Results_Class102', 'Results_Date103', 'Results_Class103', 'Results_Description091', 'Results_Description092'];\n let checkFlug = false;\n $.each($p.data.MainForm, function (index, val) {\n if (index.startsWith('Results')) {\n if (includeList.includes(index)) {\n // 処理内容\n checkFlug = true;\n }\n }\n });\n\n if (checkFlug) {\n //Class101算出者、Class102チェック者、Date103返信日、Class103返信者\n //Description091見積回答、Description092別途費用・伝達事項\"\n let logStr = [];\n logStr.push('算出者:' + resolveUserName($('#Results_Class101').val())); //Class101の値を氏名に解決して配列に格納\n logStr.push('チェック者:' + resolveUserName($('#Results_Class102').val())); //Class102の値を氏名に解決して配列に格納\n logStr.push('返信日:' + $('#Results_Date103').val()); //Date103の値を配列に格納\n logStr.push('返信者:' + resolveUserName($('#Results_Class103').val())); //Class103の値を氏名に解決して配列に格納\n\n //ラベルと内容の間に改行を入れることで、ラベルが独立した行になり、内容は次の行から表示される\n logStr.push('見積回答:' + '\\n' + $('#Results_Description091').val()); //Description091の値を配列に格納\n logStr.push('別途費用・伝達事項:' + '\\n' + $('#Results_Description092').val()); //Description092の値を配列に格納\n\n let orgLog = $('#Results_Description101').val(); //Description101の既存の値を取得\n\n //既存のログがある場合はそれを先頭にして新しいログを結合、ない場合は新しいログのみを結合\n let saveLog = orgLog ? orgLog + '\\n----------------------\\n' + logStr.join('\\n') : logStr.join('\\n');\n $p.set($('#Results_Description101'), saveLog); //Description101に保存\n }\n}\n\n//見積回答(Description091)・別途費用・伝達事項(Description092)をDescription093へ統合し、\n//Description093の内容をDescription061(見積結果)へ転記する\n$p.mergeEstimateResult = function () {\n //対象項目の変更があった場合のみ処理する\n let includeList = ['Results_Description091', 'Results_Description092'];\n let checkFlug = false;\n $.each($p.data.MainForm, function (index, val) {\n if (index.startsWith('Results')) {\n if (includeList.includes(index)) {\n checkFlug = true;\n }\n }\n });\n\n if (checkFlug) {\n //091・092を改行で結合してDescription093へ格納(内容に変更が無ければ上書きしない)\n let mergeStr = $('#Results_Description091').val() + '\\n' + $('#Results_Description092').val();\n if ($('#Results_Description093').val() !== mergeStr) {\n $p.set($('#Results_Description093'), mergeStr);\n }\n\n //Description093をDescription061へ転記(内容に変更が無ければ上書きしない)\n if ($('#Results_Description061').val() !== mergeStr) {\n $p.set($('#Results_Description061'), mergeStr);\n }\n }\n}\n\n//----------------------------------------------------------------------\n//ClassZ(①物件基本情報からのリンク元ID)が新規作成時に空欄の場合、新規作成をブロックする\n//(①物件基本情報のリンクを経由せず直接このサイトで新規作成しようとした異常系を検知)\n$p.ex.checkClassZRequired = function () {\n if ($p.action() == 'new' && !$('#Results_ClassZ').val()) {\n $p.ex.setMyMessage('new-status-red', '①物件基本情報から新規依頼を作成してください');\n return false;\n }\n return true;\n}\n\n//----------------------------------------------------------------------\n//営業積算タブ(_Tab-2)→問い合わせ情報タブ(General)への転記(同一レコード内)\n//受付日Date081→Date061、受付者Class081→Class061\n//見積依頼日Date082→Date062、見積依頼先Class083→Class063\n//見積受信日Date090→Date063、見積種別Class091→Class065\n//転記先の値に差異がある場合のみ転記し、差異が無い場合はスキップする\n$p.syncSekisanTabToGeneralTab = function () {\n let mapping = [\n { from: 'Class081', to: 'Class061' }, //受付者(Class061もUsers型のため、氏名変換せずUserIdのまま転記する)\n { from: 'Class083', to: 'Class063' }, //見積依頼先\n { from: 'Date081', to: 'Date061' }, //受付日\n { from: 'Date082', to: 'Date062' }, //見積依頼日\n { from: 'Date090', to: 'Date063' }, //見積受信日\n { from: 'Class091', to: 'Class065' }, //見積種別\n ];\n\n mapping.forEach(function (item) {\n let fromVal = $('#Results_' + item.from).val();\n if (item.resolveUser) fromVal = resolveUserName(fromVal);\n let toVal = $('#Results_' + item.to).val();\n\n //値に差異がある場合のみ転記する\n if (fromVal !== toVal) {\n $p.set($('#Results_' + item.to), fromVal);\n }\n });\n}\n\n//----------------------------------------------------------------------\n//依頼者(ClassC:単一選択)と担当者・CC一覧(Class153:複数選択)をマージし、\n//重複を除いてClassY(依頼者・担当者・CC一覧、複数選択・非表示)へ保存する\n$p.mergeClassY = function () {\n let classCVal = $('#Results_ClassC').val();\n let class153Vals = $('#Results_Class153').val() || [];\n\n let merged = [];\n if (classCVal) merged.push(classCVal);\n class153Vals.forEach(function (v) {\n if (v && !merged.includes(v)) merged.push(v);\n });\n\n $p.set($('#Results_ClassY'), JSON.stringify(merged));\n}\n\n//----------------------------------------------------------------------\n//返信予定日 Date085 変更イベントを検知して実行\n$p.on('change', 'Date085', function () {\n if ($('#Results_Date085').val() != '') {\n console.log('返信予定日が変更されました。');\n $p.replaceDate085();\n }\n});\n\n//Description082には「直前に本文へ置換した返信予定日の値」をキーとして保持する\n//(レコード保存・再読込後も同じ値が残るため、次回変更時に古い値だけを新しい値へ置換できる)\n$p.replaceDate085 = function () {\n if ($('#Results_Date085').val() != '') {\n console.log('返信予定日が変更されました。');\n //返信予定日(今回の新しい値)を取得\n let date085 = $('#Results_Date085').val();\n\n //遅延理由メッセージを取得\n let content081 = $('#Results_Description081').val();\n //前回置換に使った返信予定日(キー)をDescription082から取得\n let content082 = $('#Results_Description082').val();\n\n let newContent;\n if (content081.indexOf('%返信予定日%') !== -1) {\n //本文に未置換のプレースホルダー(%返信予定日%)が残っている場合は常に最優先で置換する\n //(2回目以降でも、遅延連絡内容欄へ新しいテンプレ文言を入力し直すと本文に前回の日付文字列が\n // 含まれず、else側のsplit/joinでは置換対象が見つからずプレースホルダーが残ってしまうため)\n newContent = content081.replace(/%返信予定日%/g, date085);\n } else if (content082 !== '' && content081.indexOf(content082) !== -1) {\n //プレースホルダーは無いが、本文中に前回の返信予定日(キー)が残っている場合はそれを新しい日付に置換\n newContent = content081.split(content082).join(date085);\n } else {\n //置換対象が本文中に見つからない場合は本文を変更しない\n newContent = content081;\n }\n\n //遅延理由を再設定する\n $p.set($('#Results_Description081'), newContent);\n\n //今回の返信予定日を次回のキーとしてDescription082に保存\n $p.set($('#Results_Description082'), date085);\n }\n}\n\n//----------------------------------------------------------------------\n//日付文字列を「年/月/日(曜日)」形式に整形する(例:\"2026/06/25\" → \"2026/6/25(木)\")\nfunction formatDateWithWeekday(dateStr) {\n if (!dateStr) return '';\n let datePart = dateStr.split(' ')[0]; //時刻が付いている場合は日付部分のみ取り出す\n let parts = datePart.split('/');\n if (parts.length < 3) return datePart; //想定外の形式の場合はそのまま返す\n\n let year = parseInt(parts[0], 10);\n let month = parseInt(parts[1], 10);\n let day = parseInt(parts[2], 10);\n let dateObj = new Date(year, month - 1, day);\n\n let weekdays = ['日', '月', '火', '水', '木', '金', '土'];\n let weekday = weekdays[dateObj.getDay()];\n\n return year + '/' + month + '/' + day + '(' + weekday + ')'; //例:2026/6/25(木)\n}\n", "Id": 1 }, { "Title": "02_添付ファイルDL.js", "New": true, "Edit": true, "Body": "/*\n@config :\n@filename : 02_添付ファイルDL.js\n@title : 02_添付ファイルDL\n@name :\n@siteIds :\n@siteTitles : 問合せ内容管理\n@disabled: false\n*/\n\n/*\ninit内部\nlet attachColumns = $('.control-attachments');\n$.each(attachColumns, function (index, value) {\n let attach = value.dataset.name;\n attachmentComments(attach);\n attachFileCheckbox(attach);\n})\n*/\n\n//----------------------------------------------------------------------\n//添付ファイル項目にボタンの追加\nfunction attachFileCheckbox(attach) {\n //管理番号 Results_ClassX\n let title = $('#Results_ClassX').val();\n\n let colName = $('#Results_' + attach + 'Field label')[0].innerHTML;\n let attachData = JSON.parse($p.getControl(attach).val());\n let zipFilename = title + '■' + colName + '■';\n\n //console.log(attachData.length);\n if (attachData.length >= 1) {\n $.each(attachData, function (index, value) {\n let checkbox = document.createElement('input');\n checkbox.type = 'checkbox';\n checkbox.style.margin = '2px';\n checkbox.style.float = 'left';\n checkbox.name = attach + '_checkbox';\n checkbox.id = value.Guid + '_checkbox';\n checkbox.value = value.Guid;\n\n $('#' + value.Guid).prepend(checkbox);\n\n });\n\n //ダウンロードボタン\n let div = document.createElement('div');\n let dlButton1 = document.createElement('button');\n dlButton1.type = 'button';\n dlButton1.id = attach + '_dlButton1';\n dlButton1.style.marginRight = '5px';\n dlButton1.innerHTML = '全ファイルDL';\n dlButton1.setAttribute('attach', attach);\n dlButton1.setAttribute('onclick', 'dlAllFiles(\"' + attach + '\",\"' + zipFilename + '全ファイルDL' + '\")');\n\n let dlButton2 = document.createElement('button');\n dlButton2.type = 'button';\n dlButton2.id = attach + '_dlButton2';\n dlButton2.style.marginRight = '5px';\n dlButton2.innerHTML = '選択DL';\n dlButton2.setAttribute('attach', attach);\n dlButton2.setAttribute('onclick', 'dlSelectedFiles(\"' + attach + '\",\"' + zipFilename + '選択DL' + '\")');\n\n div.style.margin = '5px';\n div.style.marginTop = '0px';\n div.style.marginLeft = '120px';\n div.style.marginRight = '5px';\n div.style.marginBottom = '10px';\n div.style.clear = 'both';\n div.append(dlButton1);\n div.append(dlButton2);\n $('#Results_' + attach + 'Field').after(div);\n $('#' + attach + '_dlButton1').button({\n icon: 'ui-icon-document'\n });\n $('#' + attach + '_dlButton2').button({\n icon: 'ui-icon-document'\n });\n }\n}\n\nfunction dlSelectedFiles(attach, zipFilename) {\n //console.log(zipFilename);\n //チェックがついているもののみ\n const fileList = $('input[name=\"' + attach + '_checkbox\"]:checked');\n let guidList = new Array();\n for (item of fileList) {\n //console.log(item);\n guidList.push(item.value);\n }\n\n if (guidList.length > 0) {\n dlZipAttachements(guidList, zipFilename);\n }\n\n}\n\nfunction dlAllFiles(attach, zipFilename) {\n let guidList = new Array();\n //全部\n const fileList = JSON.parse($p.getControl(attach).val());\n for (item of fileList) {\n guidList.push(item.Guid);\n }\n\n if (guidList.length > 0) {\n dlZipAttachements(guidList, zipFilename);\n }\n}\n\n/**\n * 複数ファイルを1ファイルにzip圧縮してDLする\n * @param guidList DLする添付ファイルのGUIDのリスト\n * @param zipFilename zipファイル名\n * @return なし\n */\nasync function dlZipAttachements(guidList, zipFilename) {\n var binary;\n var filename;\n const zip = new JSZip();\n const jsonReq = {\n ApiVersion: 1.1\n };\n\n for (guid of guidList) {\n await axios.post(\"/pleasanter/api/binaries/\" + guid + \"/get\", jsonReq)\n .then(function (response) {\n binary = decodeBase64(response.data.Response.Base64);\n filename = response.data.Response.FileName;\n zip.folder(zipFilename).file(filename, binary, {\n binary: true\n });\n })\n .catch(function (error) {\n console.log(error);\n })\n .finally(function () { });\n }\n saveAs(await zip.generateAsync({\n type: \"blob\"\n }), zipFilename + \".zip\");\n}\n\n/**\n * base64デコード処理\n * @param base64 base64文字列\n * @return デコードしたバイナリデータ\n */\nfunction decodeBase64(base64) {\n const bin = atob(base64.replace(/^.*,/, ''));\n var buffer = new Uint8Array(bin.length);\n for (var i = 0; i < bin.length; i++) {\n buffer[i] = bin.charCodeAt(i);\n }\n return buffer.buffer;\n}\n\n//添付ファイルのファイル名一覧を表示する(質疑ファイル・回答ファイルはボタンのみで何が添付されているか\n//分からなかったため、attach欄の下にファイル名を列挙する)。\n//messageSaveButton()が質疑送信/回答送信ボタンを持たない権限のユーザーに対してAttachments071Field/072Field\n//自体をhide()する仕様のため、Field内部(append)ではなくField外側(after)に置いて、\n//Fieldが非表示でもファイル名一覧だけは常に見えるようにする\n$p.ex.showAttachmentFileNames = function (attach) {\n let attachData = [];\n try {\n attachData = JSON.parse($p.getControl(attach).val());\n } catch (e) {\n attachData = [];\n }\n if (!attachData.length) return;\n\n let div = document.createElement('div');\n div.className = 'commentAdd nowrap';\n div.style.marginLeft = '121px';\n div.innerHTML = attachData.map(function (file) { return '・' + file.Name; }).join('
');\n $('#Results_' + attach + 'Field').after(div);\n}\n\n//説明欄にコメントがある場合、追加\nfunction attachmentComments(attach) {\n let comments = '';\n\n if ($('#Results_' + attach + 'Field>div.field-control').attr('title')) {\n comments = $('#Results_' + attach + 'Field>div.field-control').attr('title');\n }\n\n if (comments) {\n let div1 = document.createElement('div');\n div1.innerHTML = comments;\n div1.style.marginLeft = '121px';\n div1.style.fontWeight = 'bold';\n div1.style.color = '#00F';\n\n //位置調整とコメント追加\n $('#Results_' + attach + 'Field').append(div1);\n $('#Results_' + attach + 'Field').css('margin-bottom', '10px');\n }\n\n}", "Id": 2 }, { "Title": "03_質疑応答スクリプト.js", "New": true, "Edit": true, "Body": "/*\n@config :\n@filename : 03_質疑応答スクリプト.js\n@title : 03_質疑応答スクリプト\n@name :\n@siteIds :\n@siteTitles : 問合せ内容管理\n@disabled: false\n*/\n\n//----------------------------------------------------------------------\n//質疑応答機能:configs\\参考ソース\\■3_310405_Re③依頼項目\\sites\\scripts\\03_質疑応答スクリプト.js を\n//本サイト(504322)の既存予約項目(Description075/076/071、Num071/072、Class071/075/077、Date073/074、\n//Attachments071/072)に合わせて移植・拡張したもの。\n//\n//項目対応(参照元 → 本サイト)\n// Description131(質疑入力欄) → Description075「質疑内容」\n// Description132(回答入力欄) → Description076「回答内容」\n// Description135(ログ保存用) → Description071「質疑回答データ保存用」\n// Num131/132(質疑回数/回答回数) → Num071/Num072\n// Class131(質疑回答ステータス0-3) → Class071(選択肢の値・色分けとも参照元と一致)\n// Attachments131/132 → Attachments071/072\n//\n//本サイトにのみ存在し参照元スクリプトにはなかった項目は、下記の想定で組み込んでいます(要確認)。\n// Class075「質疑回答送信者」 :質疑または回答を送信した本人の氏名を、送信のたびに上書き記録\n// Class077「質疑送付先」 :質疑送信時に選択した宛先ユーザーを、ログの表示にのみ利用(通知メール送信は未実装)\n// Date073「質疑回答期日」 :質疑送信時に、$p.getHolidayTable()と同じ祝日データ(HolidaysList)を使って\n// 土日祝を除く5営業日後を自動計算して設定\n// Date074「営業積算確認日」 :営業積算が回答内容を確認した際(営業積算確認プロセス実行時)に本日日付を設定\n//\n//回答送信ボタンの表示自体はProcess「回答送信」側のView条件(ClassC:[\"Own\"])でサーバー側に強制されている\n//(ClassC=依頼者本人のみ実行可)。processScript側にも念のため同じ判定を残している\n//(processScript本体は04_プロセス処理スクリプト.jsへ統合済み。プロセスボタン共通ディスパッチャは\n// 1ファイルに1つしか定義できないため、19プロセス全件を扱う04側へ集約し、本ファイルには\n// saveQuestionMessage等の実処理関数のみを残す構成にしている)。\n//----------------------------------------------------------------------\n\n//営業積算からの質疑を保存\n$p.ex.saveQuestionMessage = function () {\n\n let message = $('#Results_Description075').val();\n let userName = $p.userName();\n let now = new Date();\n let nowStr = now.getFullYear() + '/' + (now.getMonth() + 1).toString().padStart(2, '0') + '/' + now.getDate().toString().padStart(2, '0') + ' ' +\n now.getHours().toString().padStart(2, '0') + ':' + now.getMinutes().toString().padStart(2, '0') + ':' + now.getSeconds().toString().padStart(2, '0');\n\n let messageID = 'a' + now.getFullYear() + '' + (now.getMonth() + 1).toString().padStart(2, '0') + '' + now.getDate().toString().padStart(2, '0') + '' +\n now.getHours().toString().padStart(2, '0') + '' + now.getMinutes().toString().padStart(2, '0') + '' + now.getSeconds().toString().padStart(2, '0') + '-' + $p.userId();\n let num = parseFloat($('#Results_Num071').val() || 0) + 1;\n\n //質疑送付先(Class077:複数ユーザー選択、要確認:表示形式によってはセレクタの調整が必要)\n let sendToText = $('#Results_Class077').val() || '';\n\n let data = {\n 'messageID': messageID,\n 'type': 'Question',\n 'num': toCircledNumber(num),\n 'typeStr': '営業積算からの質疑',\n 'userName': userName,\n 'sendTo': sendToText,\n 'messageTime': nowStr,\n 'messageBody': message,\n 'enabled': true,\n };\n\n //質疑回答 保管用項目に保存する\n let saveData = $('#Results_Description071').val();\n let shitsugiData;\n\n if (saveData == '') {\n shitsugiData = [];\n shitsugiData.push(data);\n } else {\n shitsugiData = JSON.parse(saveData);\n shitsugiData.push(data);\n }\n $p.set($('#Results_Description071'), JSON.stringify(shitsugiData));\n\n //送信者を記録\n $p.set($('#Results_Class075'), userName);\n\n //質疑回数をカウントアップ\n $p.set($('#Results_Num071'), num);\n\n //質疑回答ステータスを「質疑あり」に更新\n $p.set($('#Results_Class071'), '1');\n\n //質疑回答期日(土日祝を除く5営業日後)を設定\n $p.set($('#Results_Date073'), $p.ex.calcBusinessDeadline(5));\n\n //質疑ありチェックをオンにする\n $p.set($('#Results_Check071'), 'checked');\n\n //送信したら入力欄は削除する\n $p.set($('#Results_Description075'), '');\n}\n\n//依頼者からの回答を保存\n$p.ex.saveAnswerMessage = function () {\n\n let message = $('#Results_Description076').val();\n let userName = $p.userName();\n let now = new Date();\n let nowStr = now.getFullYear() + '/' + (now.getMonth() + 1).toString().padStart(2, '0') + '/' + now.getDate().toString().padStart(2, '0') + ' ' +\n now.getHours().toString().padStart(2, '0') + ':' + now.getMinutes().toString().padStart(2, '0') + ':' + now.getSeconds().toString().padStart(2, '0');\n\n let messageID = 'b' + now.getFullYear() + '' + (now.getMonth() + 1).toString().padStart(2, '0') + '' + now.getDate().toString().padStart(2, '0') + '' +\n now.getHours().toString().padStart(2, '0') + '' + now.getMinutes().toString().padStart(2, '0') + '' + now.getSeconds().toString().padStart(2, '0') + '-' + $p.userId();\n let num = parseFloat($('#Results_Num072').val() || 0) + 1;\n\n let data = {\n 'messageID': messageID,\n 'type': 'Answer',\n 'num': toCircledNumber(num),\n 'typeStr': '依頼者からの回答',\n 'userName': userName,\n 'messageTime': nowStr,\n 'messageBody': message,\n 'enabled': true,\n };\n\n //質疑回答 保管用項目に保存する\n let saveData = $('#Results_Description071').val();\n let shitsugiData;\n\n if (saveData == '') {\n shitsugiData = [];\n shitsugiData.push(data);\n } else {\n shitsugiData = JSON.parse(saveData);\n shitsugiData.push(data);\n }\n $p.set($('#Results_Description071'), JSON.stringify(shitsugiData));\n\n //送信者を記録\n $p.set($('#Results_Class075'), userName);\n\n //回答回数をカウントアップ\n $p.set($('#Results_Num072'), num);\n\n //質疑回答ステータスを「回答あり」に更新\n $p.set($('#Results_Class071'), '2');\n\n //回答ありチェックをオンにする\n $p.set($('#Results_Check072'), 'checked');\n\n //送信したら入力欄は削除する\n $p.set($('#Results_Description076'), '');\n}\n\n//営業積算が回答内容を確認\n$p.ex.confirmAnswerMessage = function () {\n let now = new Date();\n let nowStr = now.getFullYear() + '/' + (now.getMonth() + 1).toString().padStart(2, '0') + '/' + now.getDate().toString().padStart(2, '0');\n\n //営業積算確認日を設定\n $p.set($('#Results_Date074'), nowStr);\n\n //質疑回答ステータスを「営業積算確認済み」に更新\n $p.set($('#Results_Class071'), '3');\n}\n\n//質疑回答メッセージ履歴の表示\n$p.ex.messageHistory = function () {\n //質疑回数と回答回数の参照\n let num071 = parseFloat($('#Results_Num071').val());\n let num072 = parseFloat($('#Results_Num072').val());\n\n if (num071 > 0 || num072 > 0) {\n //タブの色の変更(要確認:本サイトでは質疑応答セクションは_Tab-1=FieldSetTab1に配置)\n let shitsugi_Status = $('#Results_Class071').val();\n\n switch (shitsugi_Status) {\n case '': //質疑なし\n case '0': //質疑なし\n $('a[href=\"#FieldSetTab1\"] label').text('質疑なし');\n $('a[href=\"#FieldSetTab1\"]').css('background-color', 'blue');\n $('a[href=\"#FieldSetTab1\"]').css('color', 'white');\n break;\n case '1': //質疑あり\n $('a[href=\"#FieldSetTab1\"] label').text('質疑あり');\n $('a[href=\"#FieldSetTab1\"]').css('background-color', 'red');\n $('a[href=\"#FieldSetTab1\"]').css('color', 'white');\n break;\n case '2': //回答あり\n $('a[href=\"#FieldSetTab1\"] label').text('回答あり');\n $('a[href=\"#FieldSetTab1\"]').css('background-color', 'yellow');\n $('a[href=\"#FieldSetTab1\"]').css('color', 'black');\n break;\n case '3': //営業積算確認済み\n $('a[href=\"#FieldSetTab1\"] label').text('営業積算確認済み');\n $('a[href=\"#FieldSetTab1\"]').css('background-color', 'green');\n $('a[href=\"#FieldSetTab1\"]').css('color', 'white');\n break;\n }\n\n //メッセージテーブルがすでに存在したら削除\n if ($('#messageTable').length) {\n $('#messageTable').remove();\n }\n\n //削除ボタン削除\n if ($('#messageDelete').length) {\n $('#messageDelete').remove();\n }\n\n let saveData = $('#Results_Description071').val();\n\n if (saveData) {\n //メッセージデータの取得\n let messageData = JSON.parse(saveData);\n\n let templateHtml =\n `\n \n {{#messageData}}\n \n \n \n \n \n \n \n \n \n {{/messageData}}\n \n
{{typeStr}} {{num}}{{userName}}{{messageTime}}
\n
{{{messageBody}}}
\n
`;\n\n let template = Hogan.compile(templateHtml);\n let outputHtml = template.render({\n \"messageData\": messageData\n });\n\n //質疑内容入力欄の直上にメッセージ履歴テーブルを表示する\n //(本サイトにはSectionFields番号を直接指定できる根拠がないため、既知の項目=Description075Fieldを起点に挿入)\n setTimeout(function () {\n $('#SectionFields8').append(outputHtml);\n }, 300);\n }\n\n //対応するプロセスボタン「質疑回答削除」が実在する場合のみ削除ボタンを表示(Depts・View条件にそのまま追従)\n if ($p.ex.processButtonExists('質疑回答削除')) {\n let button3 = document.createElement('button');\n button3.type = 'button';\n button3.id = 'messageDelete';\n button3.innerHTML = '質疑回答削除';\n button3.setAttribute('onclick', \"$p.ex.clickProcessByName('質疑回答削除')\");\n button3.style.margin = '5px';\n button3.style.float = 'right';\n button3.style.fontSize = '1.3em';\n\n setTimeout(function () {\n $('#Results_Description075Field').before(button3);\n $('#messageDelete').button({\n icon: 'ui-icon-document'\n });\n }, 300);\n }\n }\n}\n\n//権限外ユーザーに対して、添付欄(attach)の新規アップロード領域・既存ファイルの削除ボタンのみを非表示にする\n//(欄自体やファイル名一覧・DLリンクは残し、閲覧はできるが新規追加・削除はできない状態にする)。\n//id=\"{attach}.upload\"/\"{attach}.items\"はドット付きIDのためCSSセレクタでは属性セレクタで指定する\nfunction restrictAttachmentEdit(attach) {\n $('[id=\"' + attach + '.upload\"]').hide();\n $('[id=\"' + attach + '.items\"] .delete-file').hide();\n}\n\n//質疑・回答送信ボタン作成\n$p.ex.messageSaveButton = function () {\n //対応するプロセスボタン「質疑送信」が実在する場合のみ表示(Depts・View条件による表示制御にそのまま追従)\n if ($p.ex.processButtonExists('質疑送信') && !$('#saveQuestion').length) {\n let div1 = document.createElement('div');\n div1.style.textAlign = 'right';\n let button1 = document.createElement('button');\n button1.type = 'button';\n button1.id = 'saveQuestion';\n button1.innerHTML = '質疑送信';\n button1.setAttribute('onclick', \"$p.ex.clickProcessByName('質疑送信')\");\n button1.style.margin = '5px';\n button1.style.fontSize = '1.3em';\n div1.append(button1);\n $('#Results_Attachments071Field').after(div1);\n $('#saveQuestion').button({\n icon: 'ui-icon-document'\n });\n } else {\n //営業積算以外は質疑ファイルの新規アップロード・削除を禁止(既存ファイルの閲覧・DLは残す)\n restrictAttachmentEdit('Attachments071');\n }\n\n //対応するプロセスボタン「積算対応中へ」が実在する場合のみ表示(Depts・View条件による表示制御にそのまま追従)\n //(ボタンのラベル「営業積算確認」は維持。実行先プロセスは新プロセス仕様で「積算対応中へ」(Id:6)に統合されたため、\n // clickProcessByNameの対象名のみ変更。confirmAnswerMessage()は04_プロセス処理スクリプト.jsのcase'積算対応中へ'内で呼ぶ)\n if ($p.ex.processButtonExists('積算対応中へ') && !$('#confirmAnswer').length) {\n let div4 = document.createElement('div');\n div4.style.textAlign = 'right';\n let button4 = document.createElement('button');\n button4.type = 'button';\n button4.id = 'confirmAnswer';\n button4.innerHTML = '営業積算確認';\n button4.setAttribute('onclick', \"$p.ex.clickProcessByName('積算対応中へ')\");\n button4.style.margin = '5px';\n button4.style.fontSize = '1.3em';\n div4.append(button4);\n $('#Results_Attachments072Field').after(div4);\n $('#confirmAnswer').button({\n icon: 'ui-icon-document'\n });\n }\n\n //対応するプロセスボタン「回答送信」が実在する場合のみ表示\n //(Process「回答送信」側のView条件(ClassC:[\"Own\"])による表示制御にそのまま追従。userId直接比較は行わない)\n if ($p.ex.processButtonExists('回答送信') && !$('#saveAnswer').length) {\n let div2 = document.createElement('div');\n div2.style.textAlign = 'right';\n let button2 = document.createElement('button');\n button2.type = 'button';\n button2.id = 'saveAnswer';\n button2.innerHTML = '回答送信';\n button2.setAttribute('onclick', \"$p.ex.clickProcessByName('回答送信')\");\n button2.style.margin = '5px';\n button2.style.fontSize = '1.3em';\n div2.append(button2);\n $('#Results_Attachments072Field').after(div2);\n $('#saveAnswer').button({\n icon: 'ui-icon-document'\n });\n } else {\n //依頼者本人以外は回答ファイルの新規アップロード・削除を禁止(既存ファイルの閲覧・DLは残す)\n restrictAttachmentEdit('Attachments072');\n }\n\n}\n\n//遅延連絡ボタン作成(対応するプロセスボタン「遅延連絡」が実在する場合のみ表示。Depts・View条件にそのまま追従)\n$p.ex.delayNoticeButton = function () {\n if ($p.ex.processButtonExists('遅延連絡') && !$('#sendDelayNotice').length) {\n let div5 = document.createElement('div');\n div5.style.textAlign = 'right';\n div5.style.float = 'right';\n let button5 = document.createElement('button');\n button5.type = 'button';\n button5.id = 'sendDelayNotice';\n button5.innerHTML = '遅延連絡';\n button5.setAttribute('onclick', \"$p.ex.clickProcessByName('遅延連絡')\");\n button5.style.margin = '0px 10px 5px 5px';\n button5.style.fontSize = '1.3em';\n div5.append(button5);\n $('#Results_Description081Field').after(div5);\n $('#sendDelayNotice').button({\n icon: 'ui-icon-mail-closed'\n });\n }\n}\n\n//受付ボタン作成(受付者(Class081)欄の右横に配置。対応するプロセスボタン「受付」が実在する場合のみ表示)\n$p.ex.receiptButton = function () {\n if ($p.ex.processButtonExists('受付') && !$('#sendReceipt').length) {\n let div = document.createElement('div');\n div.style.textAlign = 'right';\n div.style.float = 'right';\n let button = document.createElement('button');\n button.type = 'button';\n button.id = 'sendReceipt';\n button.innerHTML = '受付';\n button.setAttribute('onclick', \"$p.ex.clickProcessByName('受付')\");\n button.style.margin = '0px 10px 5px 5px';\n button.style.fontSize = '1.3em';\n div.append(button);\n $('#Results_Class081Field').after(div);\n $('#sendReceipt').button({\n icon: 'ui-icon-mail-closed'\n });\n }\n}\n\n//外部見積待ちへボタン作成(見積依頼者(Class082)欄の右横に配置)\n$p.ex.externalEstimateWaitButton = function () {\n if ($p.ex.processButtonExists('外部見積待ちへ') && !$('#sendExternalEstimateWait').length) {\n let div = document.createElement('div');\n div.style.textAlign = 'right';\n div.style.float = 'right';\n let button = document.createElement('button');\n button.type = 'button';\n button.id = 'sendExternalEstimateWait';\n button.innerHTML = '外部見積待ちへ';\n button.setAttribute('onclick', \"$p.ex.clickProcessByName('外部見積待ちへ')\");\n button.style.margin = '0px 10px 5px 5px';\n button.style.fontSize = '1.3em';\n div.append(button);\n $('#Results_Class082Field').after(div);\n $('#sendExternalEstimateWait').button({\n icon: 'ui-icon-mail-closed'\n });\n }\n}\n\n//社内確認中へ・差戻しボタン作成(状況(Status)欄の右横に一列で配置)\n//「問い合わせ不要」はここから返信者(Class103)欄横(一部回答ボタンの上段)へ移動済み(inquiryUnnecessaryButton参照)\n$p.ex.statusRowButtons = function () {\n if ($('#sendInternalConfirmRow').length) {\n return; //二重生成防止\n }\n let defs = [\n { id: 'sendInternalConfirm', label: '社内確認中へ', process: '社内確認中へ' },\n { id: 'sendReturnRequest', label: '差戻し', process: '差戻し' },\n ];\n let visibleDefs = defs.filter(function (d) { return $p.ex.processButtonExists(d.process); });\n if (visibleDefs.length === 0) {\n return;\n }\n\n let div = document.createElement('div');\n div.id = 'sendInternalConfirmRow';\n div.style.textAlign = 'right';\n div.style.float = 'right';\n visibleDefs.forEach(function (d) {\n let button = document.createElement('button');\n button.type = 'button';\n button.id = d.id;\n button.innerHTML = d.label;\n button.setAttribute('onclick', \"$p.ex.clickProcessByName('\" + d.process + \"')\");\n button.style.margin = '0px 10px 5px 5px';\n button.style.fontSize = '1.3em';\n div.append(button);\n });\n $('#Results_StatusField').after(div);\n visibleDefs.forEach(function (d) {\n $('#' + d.id).button({\n icon: 'ui-icon-mail-closed'\n });\n });\n}\n\n//問い合わせ不要ボタン作成(返信者(Class103)欄の右横、一部回答・見積回答ボタンと並べて一番上段に配置)\n//対応するプロセスボタン「問い合わせ不要」が実在する場合のみ表示。Depts・View条件にそのまま追従。\n$p.ex.inquiryUnnecessaryButton = function () {\n if ($p.ex.processButtonExists('問い合わせ不要') && !$('#sendInquiryUnnecessary').length) {\n let div = document.createElement('div');\n div.style.textAlign = 'right';\n div.style.float = 'right';\n let button = document.createElement('button');\n button.type = 'button';\n button.id = 'sendInquiryUnnecessary';\n button.innerHTML = '問い合わせ不要';\n button.setAttribute('onclick', \"$p.ex.clickProcessByName('問い合わせ不要')\");\n button.style.margin = '0px 10px 5px 5px';\n button.style.fontSize = '1.3em';\n div.append(button);\n $('#Results_Class103Field').after(div);\n $('#sendInquiryUnnecessary').button({\n icon: 'ui-icon-mail-closed'\n });\n }\n}\n\n//一部回答・見積回答ボタン作成(返信者(Class103)欄の右横に、問い合わせ不要ボタンの直下に一部回答を上段・見積回答を下段で縦に配置)\n//いずれも対応するプロセスボタンが実在する場合のみ表示。Depts・View条件にそのまま追従。\n//活性/非活性のクライアント側制御は行わず、実行可否もProcess側のView条件(Status)にのみ委ねる\n$p.ex.partialAnswerButton = function () {\n if ($p.ex.processButtonExists('一部回答') && !$('#sendPartialAnswer').length) {\n let div = document.createElement('div');\n div.style.textAlign = 'right';\n div.style.float = 'right';\n let button = document.createElement('button');\n button.type = 'button';\n button.id = 'sendPartialAnswer';\n button.innerHTML = '一部回答';\n button.setAttribute('onclick', \"$p.ex.clickProcessByName('一部回答')\");\n button.style.margin = '0px 10px 5px 5px';\n button.style.fontSize = '1.3em';\n div.append(button);\n //問い合わせ不要ボタン(#sendInquiryUnnecessary)が生成済みならその直後、無ければClass103Fieldの直後に配置し、\n //問い合わせ不要の真下(画面上は右寄せの縦並びで問い合わせ不要が最上段)になるようにする\n let $anchor = $('#sendInquiryUnnecessary').closest('div');\n if ($anchor.length) {\n $anchor.after(div);\n } else {\n $('#Results_Class103Field').after(div);\n }\n $('#sendPartialAnswer').button({\n icon: 'ui-icon-mail-closed'\n });\n }\n}\n\n$p.ex.estimateReplyButton = function () {\n if ($p.ex.processButtonExists('見積回答') && !$('#sendEstimateReply').length) {\n let div6 = document.createElement('div');\n div6.style.textAlign = 'right';\n div6.style.float = 'right';\n let button6 = document.createElement('button');\n button6.type = 'button';\n button6.id = 'sendEstimateReply';\n button6.innerHTML = '見積回答';\n button6.setAttribute('onclick', \"$p.ex.clickProcessByName('見積回答')\");\n button6.style.margin = '0px 10px 5px 5px';\n button6.style.fontSize = '1.3em';\n div6.append(button6);\n //一部回答ボタン(#sendPartialAnswer)が生成済みならその直後、無ければClass103Fieldの直後に配置し、\n //一部回答の真下(画面上は右寄せの縦並びで一部回答が上段)になるようにする\n let $anchor = $('#sendPartialAnswer').closest('div');\n if ($anchor.length) {\n $anchor.after(div6);\n } else {\n $('#Results_Class103Field').after(div6);\n }\n $('#sendEstimateReply').button({\n icon: 'ui-icon-mail-closed'\n });\n }\n}\n\n//見積回答ボタン押下時、営業積算タブ添付ファイル(Attachments101)を問い合わせタブ(Description062)へ転記する\n//単一項目からの転記のため「■■■項目名■■■」の見出しは付けない\n$p.ex.transcribeEstimateAttachments = function () {\n let attachData = [];\n try {\n attachData = JSON.parse($p.getControl('Attachments101').val());\n } catch (e) {\n attachData = [];\n }\n\n let lines = attachData.map(function (file) {\n return `▷ [${file.Name}](/pleasanter/binaries/${file.Guid}/show) [▶DL](/pleasanter/binaries/${file.Guid}/download)`;\n });\n\n $p.set($('#Results_Description062'), lines.join(' \\n'));\n}\n\n//Description062の下に、見積回答ファイル(Attachments101)一括DLボタンを配置する\n//DLファイル名は「親番子番_見積回答ファイル」。Attachments101が1件も無い場合は生成しない\n$p.ex.estimateAttachmentsDLButton = function () {\n if ($('#estimateAttachmentsDL').length) {\n return; //二重生成防止\n }\n\n let attachData = [];\n try {\n attachData = JSON.parse($p.getControl('Attachments101').val());\n } catch (e) {\n attachData = [];\n }\n if (!attachData.length) {\n return; //添付ファイルが1件も無い場合は表示しない\n }\n\n let classA = $('#Results_ClassA').val(); //親番\n let classB = $('#Results_ClassB').val(); //子番\n let zipFilename = classA + classB + '_見積回答ファイル';\n\n let div = document.createElement('div');\n div.style.margin = '5px';\n div.style.float = 'right';\n let button = document.createElement('button');\n button.type = 'button';\n button.id = 'estimateAttachmentsDL';\n button.innerHTML = '一括DL';\n button.setAttribute('onclick', 'dlAllFiles(\"Attachments101\",\"' + zipFilename + '\")');\n div.append(button);\n $('#Results_Description062Field').after(div);\n $('#estimateAttachmentsDL').button({\n icon: 'ui-icon-disk'\n });\n}\n\n//「①物件基本情報へ戻る」ボタンをコマンド欄(#MainCommands)の一番左に移動する\n//(Processes側のId構成に依存しないよう、ボタンラベル文字列で対象を特定する)\n$p.ex.moveBackButtonToFirst = function () {\n let $backButton = $('button[id^=\"Process_\"]').filter(function () {\n return $(this).text().replace(/^\\s+/, '').trim() === '①物件基本情報へ戻る';\n });\n if ($backButton.length) {\n $('#MainCommands').prepend($backButton);\n }\n}\n\n//質疑回答メッセージの削除(チェックの入った履歴を無効化)\n$p.ex.messageDelete = function () {\n let messageData = JSON.parse($('#Results_Description071').val());\n\n $('input[name=\"messageDeleteCheck\"]:checked').each(function (index) {\n let messageID = $(this).val();\n messageData = messageData.map(item => {\n if (item.messageID === messageID) {\n return {\n ...item,\n enabled: false,\n type: item.type + '.Disabled'\n };\n }\n return item;\n });\n });\n $p.set($('#Results_Description071'), JSON.stringify(messageData));\n\n $p.ex.setMyMessage('new-status-green', '選択した質疑回答メッセージを削除しました');\n}\n\n//ボタンラベル文字列に一致する、現在表示されているプロセスボタンをクリックする\n//(Processes側のId構成・件数に依存しないようにするための共通ヘルパー)\n$p.ex.clickProcessByName = function (name) {\n let target = $('button[id^=\"Process_\"]').filter(function () {\n return $(this).text().replace(/^\\s+/, '').trim() === name;\n }).first();\n\n if (target.length) {\n target.click();\n } else {\n $p.ex.setMyMessage('new-status-red', '現在の状態では「' + name + '」を実行できません');\n }\n}\n\n//ボタンラベル文字列に一致する、現在表示されているプロセスボタンが実在するかどうかを判定する\n//(Depts・View条件によるプロセスボタンの表示制御にそのまま追従させるため。deptコード等の直接判定はしない)\n$p.ex.processButtonExists = function (name) {\n return $('button[id^=\"Process_\"]').filter(function () {\n return $(this).text().replace(/^\\s+/, '').trim() === name;\n }).length > 0;\n}\n\n//processScript(プロセスボタン共通ディスパッチャ)は04_プロセス処理スクリプト.jsへ統合済み。\n//本ファイルには実処理関数(saveQuestionMessage等)のみ残す。\n\n//質疑回答期日を計算(本日からholidays(#HolidaysList)を除いたN営業日後)\n$p.ex.calcBusinessDeadline = function (businessDays) {\n let holidays = $('#HolidaysList').length > 0 ? JSON.parse($('#HolidaysList').val()) : [];\n\n let limitDate = new Date();\n limitDate.setHours(0);\n limitDate.setMinutes(0);\n limitDate.setSeconds(0);\n\n let count = 0;\n while (count < businessDays) {\n limitDate.setDate(limitDate.getDate() + 1);\n let limitDateStr = limitDate.getFullYear() + '/' + (limitDate.getMonth() + 1).toString().padStart(2, '0') + '/' + limitDate.getDate().toString().padStart(2, '0');\n if (!(limitDate.getDay() == 0) && !(limitDate.getDay() == 6) && !(holidays.includes(limitDateStr))) {\n count++;\n }\n }\n\n return limitDate.getFullYear() + '/' + (limitDate.getMonth() + 1).toString().padStart(2, '0') + '/' + limitDate.getDate().toString().padStart(2, '0');\n}\n\n// numを丸数字に変換して表示\nfunction toCircledNumber(n) {\n n = Math.floor(Number(n));\n if (isNaN(n) || n < 0 || n > 100) return n;\n if (n === 0) return '⓪';\n if (n <= 20) return String.fromCharCode(9311 + n); // 9312 = ①\n if (n <= 35) return String.fromCharCode(12881 + n - 21); // 12881 = ㉑\n if (n <= 50) return String.fromCharCode(12977 + n - 36); // 12977 = ㊱\n if (n <= 100) return n; // fallback for 51-100\n}\n", "Id": 3 }, { "Title": "04_プロセス処理スクリプト.js", "New": true, "Edit": true, "Body": "/*\n@config :\n@filename : 04_プロセス処理スクリプト.js\n@title : 04_プロセス処理スクリプト.js\n@name :\n@siteIds :\n@siteTitles : プロセス実行前の処理\n@disabled: false\n*/\n\n//プロセスボタンから呼び出す共通ディスパッチャ\n//Process定義側のOnClickは $p.ex.processScript($(this)); の形(ボタン要素そのものを渡す形)。\n//procNum(数値文字列)ではなく、ボタンの表示ラベル文字列(procName)で処理を振り分ける\n//(Processes側のId構成や件数が今後変わっても影響を受けないため。\n// 3_03_質疑応答スクリプト.jsに元々あったprocessScript本体をこちらへ統合済み)\n$p.ex.processScript = async function (target) {\n let $btn = $(target);\n if (!$btn.length) {\n console.log('processScript: 対象ボタンが取得できませんでした');\n return false;\n }\n\n let procName = $btn.text().replace(/^\\s+/, '').trim();\n console.log('processScript ' + procName);\n\n let popMessage = '';\n\n //確認ダイアログを出さないプロセス名。ここにprocNameを追加すると、そのプロセスはconfirmをスキップして即実行する\n let noConfirmProcesses = [];\n\n //問い合わせ管理タブの状況(Class062)はStatusのミラー項目。プロセスボタンによるStatus変更後の\n //Class062同期は、以前ここでクライアント側$p.set()により直接行っていたが、Class062にchangeイベント\n //ハンドラ(syncStatusAndClass062)が仕込まれているため、$p.set()のchange連鎖でStatusへの逆伝播が\n //発生し、execProcess送信とタイミング競合して「データが正しくありません」を引き起こしていた\n //(2026-08-11判明)。サーバー側ServerScript(BeforeUpdate、状況Class062自動同期スクリプト.js)\n //でmodel.Class062=model.Statusとして確定させる方式へ変更したため、ここでは何もしない。\n\n // プロセス名に応じた処理(popMessageが未定義(空文字)、またはnoConfirmProcessesに含まれる場合は確認メッセージを出さず実行)\n switch (procName) {\n case '積算へ依頼':\n popMessage = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (popMessage && !noConfirmProcesses.includes(procName) && !confirm(popMessage)) return;\n //ClassG(現在の進捗)が「1:承認図後・着工中」の場合の必須項目チェック(プロセス実行後はClassG/H/Iが読取専用化されるため、実行前のここでのみチェック可能)\n if (!$p.ex.checkClassGRequiredFields()) return;\n //問合せ種別(マトリックス以外/マトリックス)に応じた必須項目チェック\n if (!$p.ex.checkInquiryTypeRequiredFields()) return;\n //Status200へ遷移し依頼ロック(ReadOnly化)される前に、依頼内容(DescriptionC)を確実にマージしておく\n //(execProcessはbefore_validateとタイミングがズレるため、ここで明示的に呼んでおかないと\n // 未マージのまま依頼が送信される場合がある)\n $p.mergeMainMessage();\n break;\n case '受付':\n popMessage = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (popMessage && !noConfirmProcesses.includes(procName) && !confirm(popMessage)) return;\n //受付日・受付者をここで設定(Process側の「データの変更」だと反映がexecProcess後(サーバー側)になり、\n //先に動く01_基本スクリプト.jsのbefore_validate/ログ転記処理が値取得できず欠落するため、ここで直接設定する)\n $p.ex.setTodayAndUser('Date081', 'Class081');\n //問い合わせ情報タブ(General)側の受付日・受付者にも同時反映する(syncSekisanTabToGeneralTabは\n //before_validateでのみ実行されexecProcess経由では走らないため、ここでも直接設定しておく)\n $p.ex.setTodayAndUser('Date061', 'Class061');\n break;\n case '質疑送信':\n popMessage = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (popMessage && !noConfirmProcesses.includes(procName) && !confirm(popMessage)) return;\n if ($('#Results_Description075').val()) {\n $p.ex.toggleRequiredMark('Description075', false);\n $p.ex.saveQuestionMessage();\n } else {\n $p.ex.toggleRequiredMark('Description075', true);\n $p.ex.setMyMessage('new-status-red', '質疑内容を入力してください');\n return false;\n }\n break;\n case '回答送信': //念のためのボタン非表示以外のサーバー側判定はProcess側View条件(ClassC:[\"Own\"])が担う\n popMessage = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (popMessage && !noConfirmProcesses.includes(procName) && !confirm(popMessage)) return;\n if ($p.userId().toString() != $('#Results_ClassC').val()) {\n $p.ex.setMyMessage('new-status-red', '回答送信は依頼者本人のみ行えます');\n return false;\n }\n if ($('#Results_Description076').val()) {\n $p.ex.toggleRequiredMark('Description076', false);\n $p.ex.saveAnswerMessage();\n } else {\n $p.ex.toggleRequiredMark('Description076', true);\n $p.ex.setMyMessage('new-status-red', '回答内容を入力してください');\n return false;\n }\n break;\n case '質疑回答削除':\n popMessage = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (popMessage && !noConfirmProcesses.includes(procName) && !confirm(popMessage)) return;\n if ($('input[name=\"messageDeleteCheck\"]:checked').length) {\n $p.ex.messageDelete();\n } else {\n $p.ex.setMyMessage('new-status-red', '削除したい質疑回答メッセージを選択してください');\n return false;\n }\n break;\n case '積算対応中へ':\n popMessage = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (popMessage && !noConfirmProcesses.includes(procName) && !confirm(popMessage)) return;\n //旧「営業積算確認」プロセスを吸収。営業積算確認日(Date074)・質疑回答ステータス(Class071='3')を更新\n $p.ex.confirmAnswerMessage();\n break;\n case '外部見積待ちへ':\n popMessage = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (popMessage && !noConfirmProcesses.includes(procName) && !confirm(popMessage)) return;\n //見積依頼日・見積依頼者をここで設定(理由は「受付」と同じ)\n $p.ex.setTodayAndUser('Date082', 'Class082');\n //問い合わせ情報タブ(General)側の見積依頼日にも同時反映する(理由は「受付」と同じ。\n //見積依頼先Class063は本プロセスでは設定しない別入力項目のため対象外)\n $p.set($('#Results_Date062'), $('#Results_Date082').val());\n break;\n case '社内確認中へ':\n popMessage = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (popMessage && !noConfirmProcesses.includes(procName) && !confirm(popMessage)) return;\n break;\n case '一部回答':\n popMessage = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (popMessage && !noConfirmProcesses.includes(procName) && !confirm(popMessage)) return;\n //返信日・返信者をここで設定(理由は「受付」と同じ)\n $p.ex.setTodayAndUser('Date103', 'Class103');\n break;\n case '見積回答':\n popMessage = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (popMessage && !noConfirmProcesses.includes(procName) && !confirm(popMessage)) return;\n //実行可否はProcess側View条件(Status)のみで担保しているため、追加の入力チェックは行わない\n //返信日・返信者をここで設定(理由は「受付」と同じ)\n $p.ex.setTodayAndUser('Date103', 'Class103');\n //営業積算タブ添付ファイル(Attachments101)を問い合わせタブ(Description062)へ転記\n $p.ex.transcribeEstimateAttachments();\n break;\n case '完了':\n popMessage = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (popMessage && !noConfirmProcesses.includes(procName) && !confirm(popMessage)) return;\n break;\n case '問い合わせ不要':\n popMessage = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (popMessage && !noConfirmProcesses.includes(procName) && !confirm(popMessage)) return;\n //見積回答欄が空欄の場合はエラー表示してプロセス実行をブロックする\n if (!$('#Results_Description091').val()) {\n $p.ex.toggleRequiredMark('Description091', true);\n $p.ex.setMyMessage('new-status-red', '見積回答を入力してください');\n return false;\n }\n $p.ex.toggleRequiredMark('Description091', false);\n //execProcessはbefore_validateとタイミングがズレるため(コメント冒頭参照)、\n //見積回答(Description091)→見積結果(Description061)への転記をここで明示的に呼んでおかないと、\n //未転記のままStatus901(問い合わせ不要)へ遷移してしまう\n $p.mergeEstimateResult();\n break;\n case '依頼修正':\n popMessage = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (popMessage && !noConfirmProcesses.includes(procName) && !confirm(popMessage)) return;\n break;\n case '差戻し':\n popMessage = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (popMessage && !noConfirmProcesses.includes(procName) && !confirm(popMessage)) return;\n break;\n case '依頼取消':\n popMessage = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (popMessage && !noConfirmProcesses.includes(procName) && !confirm(popMessage)) return;\n break;\n case '保留':\n popMessage = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (popMessage && !noConfirmProcesses.includes(procName) && !confirm(popMessage)) return;\n break;\n case '保留解除':\n popMessage = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (popMessage && !noConfirmProcesses.includes(procName) && !confirm(popMessage)) return;\n break;\n case '遅延連絡':\n popMessage = '\"' + procName + '\" 処理を実行します。よろしいですか?';\n if (popMessage && !noConfirmProcesses.includes(procName) && !confirm(popMessage)) return;\n if (!$('#Results_Description081').val()) {\n $p.ex.toggleRequiredMark('Description081', true);\n $p.ex.setMyMessage('new-status-red', '遅延連絡内容を入力してください');\n return false;\n }\n $p.ex.toggleRequiredMark('Description081', false);\n //遅延連絡日・遅延連絡者をここで設定(理由は「受付」と同じ。saveReasonLogが直後に読み取るため必須)\n $p.ex.setTodayAndUser('Date084', 'Class087');\n break;\n case '①物件基本情報へ戻る':\n //Status変更を伴わないため execProcess を経由せず直接画面遷移する\n let parentId = $('#Results_ClassZ').val();\n //自分のURL+parentIdへ遷移 自分のURLの例:https://neo999.next-hd.net/pleasanter/items/335482\n let currentUrl = window.location.href;\n let baseUrl = currentUrl.split('/items/')[0];\n let targetUrl = baseUrl + '/items/' + parentId;\n window.location.href = targetUrl;\n break;\n default:\n console.log('processScript: 未対応のプロセス名です: ' + procName);\n return false;\n }\n\n // プロセス実行\n $p.execProcess($btn);\n\n //プロセス側で設定した入力検証(ValidateInputs)が未入力エラーになった場合、\n //Pleasanterが対象項目へを\n //動的追加する。これを拾い、for属性から通常のフィールドラベル(class=\"error\"でない方)を逆引きして\n //まとめて下部にアラート表示する(必須項目名はスクリプト内にハードコードしない)\n setTimeout(function () {\n //前回このブロックが付けた強調表示は毎回クリアしてから、今回のエラー対象にのみ付け直す\n //(code-required-validateは内部管理用の目印。他のチェック関数が付けたcode-requiredとは独立して管理する)\n $('.code-required-validate').removeClass('code-required code-required-validate');\n\n let $errorLabels = $('label.error[id$=\"-error\"]');\n if ($errorLabels.length) {\n let labelTexts = [];\n $errorLabels.each(function () {\n let forAttr = $(this).attr('for');\n let $fieldLabel = $('label[for=\"' + forAttr + '\"]').not('.error').first();\n labelTexts.push($fieldLabel.length ? $fieldLabel.text().trim() : forAttr);\n //Markdown型(Description等)はビューア要素(id=\"XXX.viewer\")側も対象にする\n $('#' + forAttr + ', [id=\"' + forAttr + '.viewer\"]').addClass('code-required code-required-validate');\n });\n $p.ex.setMyMessage('new-status-red', labelTexts.join('、') + ' は必須項目です。入力してください。');\n }\n }, 300);\n\n}\n\n//----------------------------------------------------------------------\n//日付項目(dateColumn)に本日日付、ユーザー項目(userColumn)にログインユーザーを設定する。\n//以前はProcess側の「データの変更」機能で設定していたが、その反映(サーバー側)はexecProcess後になり、\n//先に動くbefore_validate側のログ転記処理(saveReasonLog/saveCalculateLog等)が値を取得できず欠落する\n//不具合があったため、execProcess呼び出し前にクライアント側で直接設定するここへ移設した\n$p.ex.setTodayAndUser = function (dateColumn, userColumn) {\n let now = new Date();\n let dateStr = now.getFullYear() + '/' + (now.getMonth() + 1).toString().padStart(2, '0') + '/' + now.getDate().toString().padStart(2, '0');\n $p.set($('#Results_' + dateColumn), dateStr);\n $p.set($('#Results_' + userColumn), $p.userId());\n}\n\n//----------------------------------------------------------------------\n//ClassG(現在の進捗)が「1:承認図後・着工中」の場合、ClassH(現場の進捗)・ClassI(必要な見積金額)・\n//DescriptionA(問い合わせ経緯)が未入力ならアラート表示(プロセス実行自体をブロックする)\n//「新規依頼」プロセス実行前のみ呼ばれる(新規依頼以降はStatusControlsによりClassG/H/Iが読取専用化されるため、01_基本スクリプト.jsのbefore_validateからここへ移設)\n$p.ex.checkClassGRequiredFields = function () {\n let candidateCols = ['ClassH', 'ClassI', 'DescriptionA'];\n if ($('#Results_ClassG').val() == '1') {\n let emptyLabels = [];\n let missingCols = [];\n if (!$('#Results_ClassH').val()) { emptyLabels.push('現場の進捗'); missingCols.push('ClassH'); }\n if (!$('#Results_ClassI').val()) { emptyLabels.push('必要な見積金額'); missingCols.push('ClassI'); }\n if (!$('#Results_DescriptionA').val()) { emptyLabels.push('問い合わせ経緯'); missingCols.push('DescriptionA'); }\n\n candidateCols.forEach(function (col) {\n $p.ex.toggleRequiredMark(col, missingCols.includes(col));\n });\n\n if (emptyLabels.length > 0) {\n window.alert(emptyLabels.join('、') + ' は必須項目です。入力してください。');\n return false;\n }\n } else {\n //ClassG≠1の場合は対象外なので強調表示クラスをクリア\n candidateCols.forEach(function (col) {\n $p.ex.toggleRequiredMark(col, false);\n });\n }\n return true;\n}\n", "Id": 4 } ], "Htmls": [ { "Title": "外部ライブラリ", "PositionType": 9000, "New": true, "Edit": true, "Body": "\n\n\n", "Id": 1 } ], "ServerScripts": [ { "Title": "祝日リスト取得スクリプト.js", "Name": "", "BeforeOpeningPage": true, "Body": "/*\n@config :\n@filename : 祝日リスト取得スクリプト.js\n@title : 祝日リスト取得スクリプト\n@name :\n@siteIds :\n@siteTitles : 問合せ内容管理\n@disabled: false\n*/\n\ntry {\n getHolidayList();\n\n //サイト内に個別設置した独自ボタン(質疑送信・回答送信・質疑回答削除・営業積算確認・受付・外部見積待ちへ・\n //社内確認中へ・一部回答・見積回答・問い合わせ不要・差戻し・遅延連絡、いずれも3_03_質疑応答スクリプト.jsの\n //clickProcessByNameで対応プロセスを呼び出す)で代替しているプロセスボタンは非表示にする。\n //それ以外のプロセスボタンはPleasanter標準の表示制御(Depts・View条件)に委ね、ここでは操作しない\n elements.DisplayType('Process_2', 3); //受付\n elements.DisplayType('Process_3', 3); //質疑送信\n elements.DisplayType('Process_4', 3); //回答送信\n elements.DisplayType('Process_5', 3); //質疑回答削除\n elements.DisplayType('Process_6', 3); //積算対応中へ(営業積算確認ボタンで代替)\n elements.DisplayType('Process_7', 3); //外部見積待ちへ\n elements.DisplayType('Process_8', 3); //社内確認中へ\n elements.DisplayType('Process_9', 3); //一部回答\n elements.DisplayType('Process_10', 3); //見積回答\n elements.DisplayType('Process_12', 3); //問い合わせ不要\n elements.DisplayType('Process_14', 3); //差戻し\n elements.DisplayType('Process_18', 3); //遅延連絡\n\n} catch (error) {\n context.Log(error);\n}\n\n//祝日判定テーブルの取得(本日時点から手前30日~先60日分をHiddenに格納)\nfunction getHolidayList() {\n let today = new Date();\n let startDate = new Date();\n let endDate = new Date();\n\n //30日前の日付を計算\n startDate.setDate(today.getDate() - 30);\n //60日後の日付を計算\n endDate.setDate(today.getDate() + 60);\n\n let startDateStr = formatDate(startDate) + ' 00:00:00';\n let endDateStr = formatDate(endDate) + ' 23:59:59';\n let filterDate = '[\"' + startDateStr + ',' + endDateStr + '\"]';\n\n let data = {\n 'View': {\n 'ColumnFilterHash': {\n 'DateA': filterDate,\n },\n 'ColumnSorterHash': {\n 'DateA': 'asc',\n }\n }\n };\n\n //祝日テーブル(SiteId: 192267)からデータを取得\n let results = items.Get(192267, JSON.stringify(data));\n context.Log(`取得した祝日の件数: ${results.Length}`);\n\n let holidays = [];\n for (let item of results) {\n holidays.push(formatDate(new Date(item.DateA)));\n }\n\n //取得した祝日日付リストをHiddenに格納\n hidden.Add('HolidaysList', JSON.stringify(holidays));\n}\n\n//日付をYYYY/MM/DD形式に整形\nfunction formatDate(date) {\n return date.getFullYear() + '/' +\n (date.getMonth() + 1).toString().padStart(2, '0') + '/' +\n date.getDate().toString().padStart(2, '0');\n}\n", "Id": 1 }, { "Title": "子番自動保存スクリプト.js", "Name": "", "AfterCreate": true, "Body": "/*\n@config :\n@filename : 子番自動保存スクリプト.js\n@title : 子番自動保存スクリプト\n@name :\n@siteIds :\n@siteTitles : 問合せ内容管理\n@disabled: false\n*/\n\ntry {\n setSubNumber();\n} catch (error) {\n context.Log(error);\n}\n\n//新規作成直後(自動採番=ClassX確定後)にClassXから子番(ClassB)を算出しDBへ保存する。\n//クライアント側 $p.setSubNumber(scripts/1_01_基本スクリプト.js.js)と同じロジック・同じガードをサーバー側にも実装し、\n//「編集画面を開かない限りClassBがDBへ保存されない」不具合に対応する。\nfunction setSubNumber() {\n let classX = model.ClassX;\n if (!classX) {\n context.Log('[子番自動保存] ClassXが空のためスキップしました。ResultId=' + model.ResultId);\n return;\n }\n\n let subNumber = classX.split('-')[1]; //管理番号を「-」で分割して子番を取得\n if (subNumber && subNumber !== model.ClassB) {\n model.ClassB = subNumber;\n model.UpdateOnExit = true; //スクリプト終了時に現在のレコード情報を自動保存\n context.Log('[子番自動保存] ClassBを保存しました。ResultId=' + model.ResultId + ' ClassB=' + subNumber);\n }\n}\n", "Id": 0 }, { "Title": "Dept25所属者取得スクリプト.js", "Name": "", "BeforeOpeningPage": true, "Body": "/*\n@config :\n@filename : Dept25所属者取得スクリプト.js\n@title : Dept25所属者取得スクリプト\n@name :\n@siteIds :\n@siteTitles : 問合せ内容管理\n@disabled: false\n*/\n\ntry {\n getDept25Members();\n} catch (error) {\n context.Log(error);\n}\n\n//Dept25(営業積算課)所属者のUserId→氏名マップを取得しHiddenへ格納する。\n//クライアント側resolveUserName()がここから読み込み、表示専用の氏名解決に使う\nfunction getDept25Members() {\n let myDept = depts.Get('25');\n let map = {};\n\n if (myDept) {\n let members = myDept.GetMembers();\n for (let m of members) {\n map[m.UserId] = m.Name;\n }\n }\n\n hidden.Add('Dept25Members', JSON.stringify(map));\n}\n", "Id": 2 }, { "Title": "状況Class062自動同期スクリプト.js", "Name": "", "BeforeUpdate": true, "Body": "/*\n@config :\n@filename : 状況Class062自動同期スクリプト.js\n@title : 状況Class062自動同期スクリプト\n@name :\n@siteIds :\n@siteTitles : 問合せ内容管理\n@disabled: false\n*/\n\n//問い合わせ管理タブの状況(Class062)を、Status(状況)の変更後の値へ同期する。\n//従来はクライアント側(4_04_プロセス処理スクリプト.js)で$p.set()により直接セットしていたが、\n//Class062のchangeイベントハンドラ(syncStatusAndClass062)がStatusへ逆伝播し、execProcess送信と\n//タイミング競合して「データが正しくありません」を引き起こしていた(2026-08-11判明)。\n//BeforeUpdate(DB保存直前)でサーバー側から直接同期する事で、クライアント側のイベント連鎖を回避する。\ntry {\n if (model.Status !== model.Class062) {\n model.Class062 = model.Status;\n context.Log('[状況Class062自動同期] ResultId=' + model.ResultId + ' Class062を' + model.Status + 'へ同期しました');\n }\n} catch (error) {\n context.Log('[状況Class062自動同期] エラー: ' + error);\n}\n", "Id": 4 }, { "Title": "問い合わせ不要理由テンプレ取得スクリプト.js", "Name": "", "BeforeOpeningPage": true, "Body": "/*\n@config :\n@filename : 問い合わせ不要理由テンプレ取得スクリプト.js\n@title : 問い合わせ不要理由テンプレ取得スクリプト\n@name :\n@siteIds :\n@siteTitles : 問合せ内容管理\n@disabled: false\n*/\n\ntry {\n getInquiryUnneededReasons();\n} catch (error) {\n context.Log(error);\n}\n\n//問い合わせ不要理由テンプレ(SiteId: 504319)を全件取得し、ResultId→内容(DescriptionA)のマップをHiddenに格納する。\n//クライアント側(01_基本スクリプト.js)がClass089(不要理由)の変更を検知し、ここから対応するDescriptionAを\n//Description091(見積回答)へ同期的に反映する。\n//旧実装はSiteSettings.Links(ChoicesTextのサイト内検索AutoPostBack)によるLookupだったが、\n//Class089変更直後にプロセスボタンを実行すると、非同期のPostback反映がexecProcess送信に間に合わず\n//Description091が更新されないまま保存される不具合があったため、この方式に変更した(2026-08-23)。\nfunction getInquiryUnneededReasons() {\n let results = items.Get(504319);\n context.Log(`取得した問い合わせ不要理由テンプレの件数: ${results.Length}`);\n\n let map = {};\n for (let item of results) {\n map[item.ResultId] = item.DescriptionA;\n }\n\n hidden.Add('InquiryUnneededReasonMap', JSON.stringify(map));\n}\n", "Id": 3 } ], "RelatingColumns": [ { "Title": "エリア-担当監督", "Columns": [ "Class003", "Class088" ], "Id": 1 } ], "AutoVerUpType": 2, "HideLink": true, "TitleSeparator": "-", "NoDisplayIfReadOnly": false, "NotInheritPermissionsWhenCreatingSite": false, "PermissionForCreating": { "ClassY": 4 }, "PermissionForUpdating": { "ClassY": 4 }, "CreateColumnAccessControls": [ { "ColumnName": "Attachments111", "Depts": [ 25, 26 ] }, { "ColumnName": "Attachments112", "Depts": [ 25, 26 ] }, { "ColumnName": "Class111", "Depts": [ 25, 26 ] }, { "ColumnName": "Attachments113", "Depts": [ 25, 26 ] }, { "ColumnName": "Description111", "Depts": [ 25, 26 ] }, { "ColumnName": "Date111", "Depts": [ 25, 26 ] } ], "UpdateColumnAccessControls": [ { "ColumnName": "Attachments111", "Depts": [ 25, 26 ] }, { "ColumnName": "Attachments112", "Depts": [ 25, 26 ] }, { "ColumnName": "Class111", "Depts": [ 25, 26 ] }, { "ColumnName": "Attachments113", "Depts": [ 25, 26 ] }, { "ColumnName": "Description111", "Depts": [ 25, 26 ] }, { "ColumnName": "Date111", "Depts": [ 25, 26 ] } ] }, "Publish": false, "DisableCrossSearch": false, "Comments": [] } ], "Data": [], "Permissions": [ { "SiteId": 504317, "Permissions": [ { "ReferenceId": 504318, "DeptId": 0, "GroupId": 0, "UserId": 995, "PermissionType": 511 }, { "ReferenceId": 504318, "DeptId": 0, "GroupId": 0, "UserId": 678, "PermissionType": 511 }, { "ReferenceId": 504318, "DeptId": 0, "GroupId": 0, "UserId": 460, "PermissionType": 511 }, { "ReferenceId": 504318, "DeptId": 25, "GroupId": 0, "UserId": 0, "PermissionType": 511 }, { "ReferenceId": 504321, "DeptId": 25, "GroupId": 0, "UserId": 0, "PermissionType": 511 }, { "ReferenceId": 504321, "DeptId": 0, "GroupId": 27, "UserId": 0, "PermissionType": 3 }, { "ReferenceId": 504321, "DeptId": 0, "GroupId": 0, "UserId": 460, "PermissionType": 511 }, { "ReferenceId": 504321, "DeptId": 0, "GroupId": 0, "UserId": 678, "PermissionType": 511 }, { "ReferenceId": 504321, "DeptId": 0, "GroupId": 0, "UserId": 995, "PermissionType": 511 }, { "ReferenceId": 504322, "DeptId": 25, "GroupId": 0, "UserId": 0, "PermissionType": 511 }, { "ReferenceId": 504322, "DeptId": 26, "GroupId": 0, "UserId": 0, "PermissionType": 7 }, { "ReferenceId": 504322, "DeptId": 0, "GroupId": 27, "UserId": 0, "PermissionType": 3 }, { "ReferenceId": 504322, "DeptId": 0, "GroupId": 0, "UserId": 460, "PermissionType": 511 }, { "ReferenceId": 504322, "DeptId": 0, "GroupId": 0, "UserId": 678, "PermissionType": 511 }, { "ReferenceId": 504322, "DeptId": 0, "GroupId": 0, "UserId": 995, "PermissionType": 511 }, { "ReferenceId": 504317, "DeptId": 0, "GroupId": 0, "UserId": 460, "PermissionType": 511 }, { "ReferenceId": 504317, "DeptId": 0, "GroupId": 27, "UserId": 0, "PermissionType": 1 } ] }, { "SiteId": 504318, "Permissions": [ { "ReferenceId": 504318, "DeptId": 0, "GroupId": 0, "UserId": 995, "PermissionType": 511 }, { "ReferenceId": 504318, "DeptId": 0, "GroupId": 0, "UserId": 678, "PermissionType": 511 }, { "ReferenceId": 504318, "DeptId": 0, "GroupId": 0, "UserId": 460, "PermissionType": 511 }, { "ReferenceId": 504318, "DeptId": 25, "GroupId": 0, "UserId": 0, "PermissionType": 511 } ] }, { "SiteId": 504319, "Permissions": [ { "ReferenceId": 504319, "DeptId": 0, "GroupId": 27, "UserId": 0, "PermissionType": 1 }, { "ReferenceId": 504319, "DeptId": 0, "GroupId": 0, "UserId": 995, "PermissionType": 511 }, { "ReferenceId": 504319, "DeptId": 0, "GroupId": 0, "UserId": 460, "PermissionType": 511 }, { "ReferenceId": 504319, "DeptId": 25, "GroupId": 0, "UserId": 0, "PermissionType": 511 }, { "ReferenceId": 504319, "DeptId": 0, "GroupId": 0, "UserId": 678, "PermissionType": 511 } ] }, { "SiteId": 504320, "Permissions": [ { "ReferenceId": 504320, "DeptId": 0, "GroupId": 0, "UserId": 460, "PermissionType": 511 }, { "ReferenceId": 504320, "DeptId": 0, "GroupId": 27, "UserId": 0, "PermissionType": 1 }, { "ReferenceId": 504320, "DeptId": 0, "GroupId": 0, "UserId": 995, "PermissionType": 511 }, { "ReferenceId": 504320, "DeptId": 25, "GroupId": 0, "UserId": 0, "PermissionType": 511 }, { "ReferenceId": 504320, "DeptId": 0, "GroupId": 0, "UserId": 678, "PermissionType": 511 } ] }, { "SiteId": 504321, "Permissions": [ { "ReferenceId": 504472, "DeptId": 0, "GroupId": 0, "UserId": 1100, "PermissionType": 4 }, { "ReferenceId": 504472, "DeptId": 0, "GroupId": 0, "UserId": 694, "PermissionType": 4 }, { "ReferenceId": 509221, "DeptId": 0, "GroupId": 0, "UserId": 1046, "PermissionType": 4 }, { "ReferenceId": 509221, "DeptId": 0, "GroupId": 0, "UserId": 932, "PermissionType": 4 }, { "ReferenceId": 509221, "DeptId": 0, "GroupId": 0, "UserId": 806, "PermissionType": 4 }, { "ReferenceId": 509221, "DeptId": 0, "GroupId": 0, "UserId": 730, "PermissionType": 4 }, { "ReferenceId": 509221, "DeptId": 0, "GroupId": 0, "UserId": 1037, "PermissionType": 4 }, { "ReferenceId": 509325, "DeptId": 0, "GroupId": 0, "UserId": 898, "PermissionType": 4 }, { "ReferenceId": 509325, "DeptId": 0, "GroupId": 0, "UserId": 1057, "PermissionType": 4 }, { "ReferenceId": 509325, "DeptId": 0, "GroupId": 0, "UserId": 897, "PermissionType": 4 }, { "ReferenceId": 509325, "DeptId": 0, "GroupId": 0, "UserId": 949, "PermissionType": 4 }, { "ReferenceId": 509325, "DeptId": 0, "GroupId": 0, "UserId": 850, "PermissionType": 4 }, { "ReferenceId": 504321, "DeptId": 25, "GroupId": 0, "UserId": 0, "PermissionType": 511 }, { "ReferenceId": 504321, "DeptId": 0, "GroupId": 27, "UserId": 0, "PermissionType": 3 }, { "ReferenceId": 504321, "DeptId": 0, "GroupId": 0, "UserId": 460, "PermissionType": 511 }, { "ReferenceId": 504321, "DeptId": 0, "GroupId": 0, "UserId": 678, "PermissionType": 511 }, { "ReferenceId": 504321, "DeptId": 0, "GroupId": 0, "UserId": 995, "PermissionType": 511 }, { "ReferenceId": 507178, "DeptId": 0, "GroupId": 0, "UserId": 426, "PermissionType": 4 }, { "ReferenceId": 507178, "DeptId": 0, "GroupId": 0, "UserId": 665, "PermissionType": 4 }, { "ReferenceId": 507178, "DeptId": 0, "GroupId": 0, "UserId": 596, "PermissionType": 4 } ] }, { "SiteId": 504322, "Permissions": [ { "ReferenceId": 504473, "DeptId": 0, "GroupId": 0, "UserId": 1100, "PermissionType": 4 }, { "ReferenceId": 504473, "DeptId": 0, "GroupId": 0, "UserId": 694, "PermissionType": 4 }, { "ReferenceId": 509224, "DeptId": 0, "GroupId": 0, "UserId": 1046, "PermissionType": 4 }, { "ReferenceId": 509224, "DeptId": 0, "GroupId": 0, "UserId": 932, "PermissionType": 4 }, { "ReferenceId": 509224, "DeptId": 0, "GroupId": 0, "UserId": 806, "PermissionType": 4 }, { "ReferenceId": 509224, "DeptId": 0, "GroupId": 0, "UserId": 730, "PermissionType": 4 }, { "ReferenceId": 509224, "DeptId": 0, "GroupId": 0, "UserId": 1037, "PermissionType": 4 }, { "ReferenceId": 509329, "DeptId": 0, "GroupId": 0, "UserId": 898, "PermissionType": 4 }, { "ReferenceId": 509329, "DeptId": 0, "GroupId": 0, "UserId": 1057, "PermissionType": 4 }, { "ReferenceId": 509329, "DeptId": 0, "GroupId": 0, "UserId": 897, "PermissionType": 4 }, { "ReferenceId": 509329, "DeptId": 0, "GroupId": 0, "UserId": 949, "PermissionType": 4 }, { "ReferenceId": 509329, "DeptId": 0, "GroupId": 0, "UserId": 850, "PermissionType": 4 }, { "ReferenceId": 504322, "DeptId": 25, "GroupId": 0, "UserId": 0, "PermissionType": 511 }, { "ReferenceId": 504322, "DeptId": 26, "GroupId": 0, "UserId": 0, "PermissionType": 7 }, { "ReferenceId": 504322, "DeptId": 0, "GroupId": 27, "UserId": 0, "PermissionType": 3 }, { "ReferenceId": 504322, "DeptId": 0, "GroupId": 0, "UserId": 460, "PermissionType": 511 }, { "ReferenceId": 504322, "DeptId": 0, "GroupId": 0, "UserId": 678, "PermissionType": 511 }, { "ReferenceId": 504322, "DeptId": 0, "GroupId": 0, "UserId": 995, "PermissionType": 511 } ] } ], "PermissionIdList": { "DeptIdList": [ { "DeptId": 25, "DeptCode": "10106", "DeptName": "営業積算課" }, { "DeptId": 26, "DeptCode": "10107", "DeptName": "積算発注管理課" } ], "GroupIdList": [ { "GroupId": 27, "GroupName": "ネクストグループ全社員" } ], "UserIdList": [ { "UserId": 995, "LoginId": "SystemUser", "UserCode": "", "Name": "システムユーザ" }, { "UserId": 678, "LoginId": "next17483", "UserCode": "", "Name": "高橋 光晴" }, { "UserId": 460, "LoginId": "ntkco12216", "UserCode": "", "Name": "野木 健一郎" }, { "UserId": 1100, "LoginId": "test003", "UserCode": "", "Name": "テストユーザ" }, { "UserId": 694, "LoginId": "ntkco13247", "UserCode": "", "Name": "石田 直樹" }, { "UserId": 1046, "LoginId": "next19612", "UserCode": "", "Name": "大谷 寛" }, { "UserId": 932, "LoginId": "next18516", "UserCode": "", "Name": "津原 陸斗" }, { "UserId": 806, "LoginId": "next14298", "UserCode": "", "Name": "田ノ岡 春菜" }, { "UserId": 730, "LoginId": "ntkco13276", "UserCode": "", "Name": "田中 勇一" }, { "UserId": 1037, "LoginId": "next19605", "UserCode": "", "Name": "濱口 宏之" }, { "UserId": 898, "LoginId": "kmjco01482", "UserCode": "", "Name": "会田 智恵" }, { "UserId": 1057, "LoginId": "kmjco34591", "UserCode": "", "Name": "秋本 周作" }, { "UserId": 897, "LoginId": "kmjco01461", "UserCode": "", "Name": "植田 寛人" }, { "UserId": 949, "LoginId": "kmjco32574", "UserCode": "", "Name": "立川 和貴" }, { "UserId": 850, "LoginId": "next16394", "UserCode": "", "Name": "髙須 友菜" }, { "UserId": 426, "LoginId": "ntkco5045", "UserCode": "", "Name": "遠藤 晃太" }, { "UserId": 665, "LoginId": "akco4190", "UserCode": "", "Name": "市川 典正" }, { "UserId": 596, "LoginId": "akco5198", "UserCode": "", "Name": "池戸 功輝" } ] } }