質問編集履歴
1
参考までにChatGPTに質問した結果を追記
test
CHANGED
File without changes
|
test
CHANGED
@@ -141,3 +141,188 @@
|
|
141
141
|
|
142
142
|
### 補足
|
143
143
|
特になし
|
144
|
+
|
145
|
+
---
|
146
|
+
---
|
147
|
+
|
148
|
+
### その後追記(参考までにChatGPTに質問した結果を追記)
|
149
|
+
試しに、ChatGPT o4-mini(プログラミング領域特化モデル)に尋ねて見たところこのような結果が出力されました。
|
150
|
+
|
151
|
+
### プロンプト
|
152
|
+
```プロンプト
|
153
|
+
ある会社では従業員情報を下記のようなNoSQLのドキュメント指向データベースに保存している。
|
154
|
+
従業員情報は、従業員自身が社内ポータルサイトで検索・閲覧することができる。
|
155
|
+
社内ポータルサイトは、ログインID/PWの他に、部署名と役職名も入力した上でログインする必要がある。
|
156
|
+
|
157
|
+
公開範囲・・・ログイン者に応じて表示するかしないかを設定したもの。
|
158
|
+
例えば、西村の場合、ログイン者が営業部または技術部の課長以上のみに表示するように公開範囲を設定しています(ログイン者がリーダーだったり、人事部だったりした場合は表示しない)
|
159
|
+
※{}の場合は全員に公開の意味です。
|
160
|
+
例)公開範囲=役職:{}、部署:技術部だったら、技術部の人には誰でも公開し、技術部以外の人だったら非公開にします。
|
161
|
+
|
162
|
+
以下のJSONはNoSQLの構造です。
|
163
|
+
{
|
164
|
+
"従業員": {
|
165
|
+
"西村": {
|
166
|
+
"年齢": 25,
|
167
|
+
"月給": "30万円",
|
168
|
+
"婚姻歴": "あり",
|
169
|
+
"部署": "技術部",
|
170
|
+
"役職": "平社員",
|
171
|
+
"公開範囲": {
|
172
|
+
"役職": "課長以上",
|
173
|
+
"部署": "営業部,技術部"
|
174
|
+
}
|
175
|
+
},
|
176
|
+
"田中": {
|
177
|
+
"年齢": 40,
|
178
|
+
"月給": "35万円",
|
179
|
+
"婚姻歴": "なし",
|
180
|
+
"部署": "技術部",
|
181
|
+
"役職": "平社員",
|
182
|
+
"公開範囲": {}
|
183
|
+
},
|
184
|
+
"秋山": {
|
185
|
+
"年齢": 31,
|
186
|
+
"月給": "60万円",
|
187
|
+
"婚姻歴": "なし",
|
188
|
+
"部署": "人事部",
|
189
|
+
"役職": "平社員",
|
190
|
+
"公開範囲": {
|
191
|
+
"役職": {},
|
192
|
+
"部署": "技術部"
|
193
|
+
}
|
194
|
+
},
|
195
|
+
"小田": {
|
196
|
+
"年齢": 45,
|
197
|
+
"月給": "70万円",
|
198
|
+
"婚姻歴": "あり",
|
199
|
+
"部署": "営業部",
|
200
|
+
"役職": "リーダー",
|
201
|
+
"公開範囲": {
|
202
|
+
"役職": "リーダー以上",
|
203
|
+
"部署": "人事部"
|
204
|
+
}
|
205
|
+
},
|
206
|
+
"木村": {
|
207
|
+
"年齢": 33,
|
208
|
+
"月給": "83万円",
|
209
|
+
"婚姻歴": "あり",
|
210
|
+
"部署": "技術部",
|
211
|
+
"役職": "課長",
|
212
|
+
"公開範囲": {
|
213
|
+
"役職": "課長以上",
|
214
|
+
"部署": {}
|
215
|
+
}
|
216
|
+
},
|
217
|
+
"岡部": {
|
218
|
+
"年齢": 56,
|
219
|
+
"月給": "130万円",
|
220
|
+
"婚姻歴": "なし",
|
221
|
+
"部署": "秘書室",
|
222
|
+
"役職": "部長",
|
223
|
+
"公開範囲": {
|
224
|
+
"役職": "課長以上",
|
225
|
+
"部署": "営業部,技術部,人事部"
|
226
|
+
}
|
227
|
+
}
|
228
|
+
}
|
229
|
+
}
|
230
|
+
|
231
|
+
こんなDB検索を実現する際、どのようにDartプログラムを組めばいいでしょうか?
|
232
|
+
|
233
|
+
例1)秋山がログインしました。ポータルサイト側の検索項目に「部署:技術部」で検索条件を掛けたとします。
|
234
|
+
その場合、「西村、田中、木村」がヒットしますが、秋山は人事部の平社員です。なので、西村と木村はヒットされず、「田中のみ」を表示したいです。
|
235
|
+
|
236
|
+
|
237
|
+
例2)岡部がログインしました。 ポータルサイト側の検索項目に「全社員を対象」で検索条件を掛けたとします。 その場合、「西村、田中、秋山、小田、木村、岡部」がヒットしますが、岡部は秘書室の部長です。 なので、「田中、木村」を表示したいです。
|
238
|
+
|
239
|
+
一般的なソースコードは「final userDoc = await FirebaseFirestore.instance.collection('従業員').doc('西村') .get();」になると思います。上記の「例1,例2」を実現するためのプログラムを作成してください。
|
240
|
+
```
|
241
|
+
|
242
|
+
### 出力結果
|
243
|
+
|
244
|
+
```ここに言語を入力
|
245
|
+
✅ 前提
|
246
|
+
Firestore コレクション名: 従業員
|
247
|
+
各ドキュメント名が従業員名(例: 西村, 田中)
|
248
|
+
ログイン情報として 部署 と 役職 を使って可視性チェック
|
249
|
+
公開範囲に基づいて、表示対象を制限
|
250
|
+
|
251
|
+
✅ Dartコード:アクセス制御付きの従業員検索
|
252
|
+
import 'package:cloud_firestore/cloud_firestore.dart';
|
253
|
+
|
254
|
+
Future<List<String>> fetchVisibleEmployees({
|
255
|
+
required String loginUserName,
|
256
|
+
required String loginDepartment,
|
257
|
+
required String loginPosition,
|
258
|
+
String? searchDepartment,
|
259
|
+
}) async {
|
260
|
+
final employeeSnapshot = await FirebaseFirestore.instance.collection('従業員').get();
|
261
|
+
final allEmployees = employeeSnapshot.docs;
|
262
|
+
|
263
|
+
// 役職の序列定義(昇順)
|
264
|
+
const positionHierarchy = ['平社員', 'リーダー', '課長', '部長', '本部長', '役員'];
|
265
|
+
|
266
|
+
int getRank(String? position) {
|
267
|
+
return positionHierarchy.indexOf(position ?? '');
|
268
|
+
}
|
269
|
+
|
270
|
+
List<String> visibleEmployees = [];
|
271
|
+
|
272
|
+
for (var doc in allEmployees) {
|
273
|
+
final data = doc.data();
|
274
|
+
final name = doc.id;
|
275
|
+
|
276
|
+
// 自分自身は非表示(必要であれば除外)
|
277
|
+
if (name == loginUserName) continue;
|
278
|
+
|
279
|
+
// 検索フィルタ
|
280
|
+
if (searchDepartment != null && data['部署'] != searchDepartment) continue;
|
281
|
+
|
282
|
+
final visibility = data['公開範囲'] as Map<String, dynamic>? ?? {};
|
283
|
+
final allowedPositions = (visibility['役職'] as String?)?.split(',') ?? [];
|
284
|
+
final allowedDepartments = (visibility['部署'] as String?)?.split(',') ?? [];
|
285
|
+
|
286
|
+
// 公開条件チェック
|
287
|
+
final isPublicToAll = visibility.isEmpty;
|
288
|
+
final isPositionMatch = allowedPositions.isEmpty || getRank(loginPosition) >= getRank(allowedPositions.first);
|
289
|
+
final isDepartmentMatch = allowedDepartments.isEmpty || allowedDepartments.contains(loginDepartment);
|
290
|
+
|
291
|
+
if (isPublicToAll || (isPositionMatch && isDepartmentMatch)) {
|
292
|
+
visibleEmployees.add(name);
|
293
|
+
}
|
294
|
+
}
|
295
|
+
|
296
|
+
return visibleEmployees;
|
297
|
+
}
|
298
|
+
|
299
|
+
✅ 使い方例
|
300
|
+
例1: 秋山(人事部・平社員)が「技術部」で検索
|
301
|
+
final result = await fetchVisibleEmployees(
|
302
|
+
loginUserName: '秋山',
|
303
|
+
loginDepartment: '人事部',
|
304
|
+
loginPosition: '平社員',
|
305
|
+
searchDepartment: '技術部',
|
306
|
+
);
|
307
|
+
// → 出力: ['田中']
|
308
|
+
|
309
|
+
例2: 岡部(秘書室・部長)が全社員検索
|
310
|
+
dart
|
311
|
+
コピーする
|
312
|
+
編集する
|
313
|
+
final result = await fetchVisibleEmployees(
|
314
|
+
loginUserName: '岡部',
|
315
|
+
loginDepartment: '秘書室',
|
316
|
+
loginPosition: '部長',
|
317
|
+
);
|
318
|
+
// → 出力: ['田中', '木村']
|
319
|
+
|
320
|
+
🔍 解説
|
321
|
+
getRank() によって役職の序列比較を可能にしています。
|
322
|
+
|
323
|
+
公開範囲が {}(空)の場合は全員に公開。
|
324
|
+
|
325
|
+
"課長以上" や "リーダー以上" のような表現ではなく、明示的な役職名を , 区切りで定義している前提で設計しています。
|
326
|
+
|
327
|
+
より柔軟にするには "以上" ロジックに合わせて条件分岐を追加する必要があります(必要なら拡張可能です)。
|
328
|
+
```
|