Line data Source code
1 : // Package meta は、国・住所用途・性別などのメタ情報を扱うユースケースを提供します。
2 : package meta
3 :
4 : import (
5 : "crypto/sha1"
6 : "encoding/hex"
7 : "sort"
8 :
9 : "resume/internal/domain/entity"
10 : )
11 :
12 : // assembleAddressPurpose は、住所用途エンティティの配列と「コード→表示名」を解決する関数を受け取り、
13 : // DTO のスライスと ETag を組み立てます。resolve は (code, fallbackDisplayName) -> label を返す関数です。
14 : func assembleAddressPurpose(
15 : list []entity.AddressPurpose,
16 : resolve func(code, fallback string) (string, string),
17 0 : ) ListAddressPurposeOutput {
18 0 :
19 0 : opts := make([]AddressPurposeDTO, 0, len(list))
20 0 : for _, ap := range list {
21 0 : label, text := ap.Code, ap.Code
22 0 : if resolve != nil {
23 0 : label, text = resolve(ap.Code, ap.DisplayName)
24 0 : }
25 0 : opts = append(opts, AddressPurposeDTO{
26 0 : ID: ap.ID,
27 0 : Code: ap.Code,
28 0 : Label: label,
29 0 : Text: text,
30 0 : Value: ap.ID,
31 0 : Disabled: false,
32 0 : SortOrder: ap.SortOrder,
33 0 : })
34 : }
35 :
36 : // 並び順: sort_order ASC, value ASC
37 0 : sort.SliceStable(opts, func(i, j int) bool {
38 0 : if opts[i].SortOrder == opts[j].SortOrder {
39 0 : return opts[i].Code < opts[j].Code
40 0 : }
41 0 : return opts[i].SortOrder < opts[j].SortOrder
42 : })
43 :
44 : // 弱い ETag(value のみでOK)
45 0 : h := sha1.New()
46 0 : for _, o := range opts {
47 0 : _, _ = h.Write([]byte(o.Code))
48 0 : _, _ = h.Write([]byte{0})
49 0 : }
50 0 : etag := `W/"` + hex.EncodeToString(h.Sum(nil)) + `"`
51 0 :
52 0 : return ListAddressPurposeOutput{
53 0 : Items: opts,
54 0 : ETag: etag,
55 0 : }
56 : }
57 :
58 : // assembleGender は、性別エンティティの配列と「コード→表示名」を解決する関数を受け取り、
59 : // DTO のスライスと ETag を組み立てます。resolve は (code, fallbackDisplayName) -> label を返す関数です。
60 : func assembleGender(
61 : list []entity.Gender,
62 : resolve func(code, fallback string) (string, string),
63 0 : ) ListGenderOutput {
64 0 : opts := make([]GenderDTO, 0, len(list))
65 0 : for _, gn := range list {
66 0 : label, text := gn.Code, gn.Code
67 0 : if resolve != nil {
68 0 : label, text = resolve(gn.Code, gn.Code)
69 0 : }
70 0 : opts = append(opts, GenderDTO{
71 0 : ID: gn.ID,
72 0 : Code: gn.Code,
73 0 : Label: label,
74 0 : Text: text,
75 0 : Value: gn.ID,
76 0 : IsActive: gn.IsActive,
77 0 : SortOrder: gn.SortOrder,
78 0 : })
79 : }
80 :
81 : // 並び順: sort_order ASC, value ASC
82 0 : sort.SliceStable(opts, func(i, j int) bool {
83 0 : if opts[i].SortOrder == opts[j].SortOrder {
84 0 : return opts[i].Code < opts[j].Code
85 0 : }
86 0 : return opts[i].SortOrder < opts[j].SortOrder
87 : })
88 :
89 : // 弱い ETag(value のみでOK)
90 0 : h := sha1.New()
91 0 : for _, o := range opts {
92 0 : _, _ = h.Write([]byte(o.Code))
93 0 : _, _ = h.Write([]byte{0})
94 0 : }
95 0 : etag := `W/"` + hex.EncodeToString(h.Sum(nil)) + `"`
96 0 :
97 0 : return ListGenderOutput{
98 0 : Items: opts,
99 0 : ETag: etag,
100 0 : }
101 : }
102 :
103 : // assembleCountry は、国エンティティの配列と「コード→表示名」を解決する関数を受け取り、
104 : // DTO のスライスと ETag を組み立てます。resolve は (code, fallbackDisplayName) -> label を返す関数です。
105 : func assembleCountry(
106 : list []entity.Country,
107 : resolve func(code, fallback string) (string, string),
108 0 : ) ListCountryOutput {
109 0 : opts := make([]CountryDTO, 0, len(list))
110 0 : for _, cn := range list {
111 0 : label, text := cn.Code, cn.Code
112 0 : if resolve != nil {
113 0 : label, text = resolve(cn.Code, cn.Code)
114 0 : }
115 0 : opts = append(opts, CountryDTO{
116 0 : Value: cn.Code,
117 0 : Label: label,
118 0 : Text: text,
119 0 : })
120 : }
121 :
122 0 : h := sha1.New()
123 0 : for _, o := range opts {
124 0 : _, _ = h.Write([]byte(o.Value))
125 0 : _, _ = h.Write([]byte{0})
126 0 : }
127 0 : etag := `W/"` + hex.EncodeToString(h.Sum(nil)) + `"`
128 0 :
129 0 : return ListCountryOutput{
130 0 : Items: opts,
131 0 : ETag: etag,
132 0 : }
133 : }
134 :
135 : // assembleEducationStatus は、学歴状態エンティティの配列と「コード→表示名」を解決する関数を受け取り、
136 : // DTO のスライスと ETag を組み立てます。resolve は (code, fallbackDisplayName) -> label を返す関数です。
137 : func assembleEducationStatus(
138 : list []entity.EducationStatus,
139 : resolve func(code, fallback string) (string, string),
140 0 : ) ListEducationStatusOutput {
141 0 : opts := make([]EducationStatusDTO, 0, len(list))
142 0 : for _, es := range list {
143 0 : label, text := es.Code, es.Code
144 0 : if resolve != nil {
145 0 : label, text = resolve(es.Code, es.Code)
146 0 : }
147 0 : opts = append(opts, EducationStatusDTO{
148 0 : ID: es.ID,
149 0 : Code: es.Code,
150 0 : Label: label,
151 0 : Text: text,
152 0 : Value: es.ID,
153 0 : Disabled: false,
154 0 : SortOrder: es.SortOrder,
155 0 : })
156 : }
157 :
158 0 : sort.SliceStable(opts, func(i, j int) bool {
159 0 : if opts[i].SortOrder == opts[j].SortOrder {
160 0 : return opts[i].Code < opts[j].Code
161 0 : }
162 0 : return opts[i].SortOrder < opts[j].SortOrder
163 : })
164 :
165 0 : h := sha1.New()
166 0 : for _, o := range opts {
167 0 : _, _ = h.Write([]byte(o.Code))
168 0 : _, _ = h.Write([]byte{0})
169 0 : }
170 0 : etag := `W/"` + hex.EncodeToString(h.Sum(nil)) + `"`
171 0 : return ListEducationStatusOutput{
172 0 : Items: opts,
173 0 : ETag: etag,
174 0 : }
175 : }
176 :
177 : // assembleDegreeType は、学位種別エンティティの配列と「コード→表示名」を解決する関数を受け取り、
178 : // DTO のスライスと ETag を組み立てます。resolve は (code, fallbackDisplayName) -> label を返す関数です。
179 : func assembleDegreeType(
180 : list []entity.DegreeType,
181 : resolve func(code, fallback string) (string, string),
182 0 : ) ListDegreeTypeOutput {
183 0 : opts := make([]DegreeTypeDTO, 0, len(list))
184 0 : for _, dt := range list {
185 0 : label, text := dt.Code, dt.Code
186 0 : if resolve != nil {
187 0 : label, text = resolve(dt.Code, dt.Code)
188 0 : }
189 0 : opts = append(opts, DegreeTypeDTO{
190 0 : ID: dt.ID,
191 0 : Code: dt.Code,
192 0 : Label: label,
193 0 : Text: text,
194 0 : Value: dt.ID,
195 0 : Disabled: false,
196 0 : SortOrder: dt.SortOrder,
197 0 : })
198 : }
199 0 : sort.SliceStable(opts, func(i, j int) bool {
200 0 : if opts[i].SortOrder == opts[j].SortOrder {
201 0 : return opts[i].Code < opts[j].Code
202 0 : }
203 0 : return opts[i].SortOrder < opts[j].SortOrder
204 : })
205 :
206 0 : h := sha1.New()
207 0 : for _, o := range opts {
208 0 : _, _ = h.Write([]byte(o.Code))
209 0 : _, _ = h.Write([]byte{0})
210 0 : }
211 0 : etag := `W/"` + hex.EncodeToString(h.Sum(nil)) + `"`
212 0 : return ListDegreeTypeOutput{
213 0 : Items: opts,
214 0 : ETag: etag,
215 0 : }
216 : }
217 :
218 : // assembleSkillCategory は、スキルカテゴリエンティティの配列と「コード→表示名」を解決する関数を受け取り、
219 : // DTO のスライスと ETag を組み立てます。resolve は (code, fallbackDisplayName) -> label を返す関数です。
220 : func assembleSkillCategory(
221 : list []entity.SkillCategory,
222 : resolve func(code, fallback string) (string, string),
223 0 : ) ListSkillCategoryOutput {
224 0 : opts := make([]SkillCategoryDTO, 0, len(list))
225 0 : for _, sc := range list {
226 0 : label, text := sc.Code, sc.Code
227 0 : if resolve != nil {
228 0 : label, text = resolve(sc.Code, sc.Code)
229 0 : }
230 0 : opts = append(opts, SkillCategoryDTO{
231 0 : ID: sc.ID,
232 0 : Code: sc.Code,
233 0 : Label: label,
234 0 : Text: text,
235 0 : Value: sc.ID,
236 0 : Disabled: false,
237 0 : SortOrder: sc.SortOrder,
238 0 : })
239 : }
240 0 : sort.SliceStable(opts, func(i, j int) bool {
241 0 : if opts[i].SortOrder == opts[j].SortOrder {
242 0 : return opts[i].Code < opts[j].Code
243 0 : }
244 0 : return opts[i].SortOrder < opts[j].SortOrder
245 : })
246 :
247 0 : h := sha1.New()
248 0 : for _, o := range opts {
249 0 : _, _ = h.Write([]byte(o.Code))
250 0 : _, _ = h.Write([]byte{0})
251 0 : }
252 0 : etag := `W/"` + hex.EncodeToString(h.Sum(nil)) + `"`
253 0 : return ListSkillCategoryOutput{
254 0 : Items: opts,
255 0 : ETag: etag,
256 0 : }
257 : }
258 :
259 : // assembleOccupation は、職域エンティティの配列と「コード→表示名」を解決する関数を受け取り、
260 : // DTO のスライスと ETag を組み立てます。resolve は (code, fallbackDisplayName) -> label を返す関数です。
261 : func assembleOccupation(
262 : list []entity.Occupation,
263 : resolve func(code, fallback string) (string, string),
264 0 : ) ListOccupationOutput {
265 0 : opts := make([]OccupationDTO, 0, len(list))
266 0 : for _, sc := range list {
267 0 : label, text := sc.Code, sc.Code
268 0 : if resolve != nil {
269 0 : label, text = resolve(sc.Code, sc.Code)
270 0 : }
271 0 : opts = append(opts, OccupationDTO{
272 0 : ID: sc.ID,
273 0 : OccupationTemplateID: sc.OccupationTemplateID,
274 0 : Code: sc.Code,
275 0 : Label: label,
276 0 : Text: text,
277 0 : Value: sc.ID,
278 0 : Disabled: false,
279 0 : SortOrder: sc.SortOrder,
280 0 : })
281 : }
282 0 : sort.SliceStable(opts, func(i, j int) bool {
283 0 : if opts[i].SortOrder == opts[j].SortOrder {
284 0 : return opts[i].Code < opts[j].Code
285 0 : }
286 0 : return opts[i].SortOrder < opts[j].SortOrder
287 : })
288 :
289 0 : h := sha1.New()
290 0 : for _, o := range opts {
291 0 : _, _ = h.Write([]byte(o.Code))
292 0 : _, _ = h.Write([]byte{0})
293 0 : }
294 0 : etag := `W/"` + hex.EncodeToString(h.Sum(nil)) + `"`
295 0 : return ListOccupationOutput{
296 0 : Items: opts,
297 0 : ETag: etag,
298 0 : }
299 : }
300 :
301 : // assembleSkillLevel は、スキルレベルエンティティの配列と「コード→表示名+説明コード+説明文」を解決する関数を受け取り、
302 : // DTO のスライスと ETag を組み立てます。resolve は (code, fallbackDisplayName) -> label を返す関数です。
303 : func assembleSkillLevel(
304 : list []entity.SkillLevel,
305 : resolve func(code, fallback string) (string, string, string, string),
306 0 : ) ListSkillLevelOutput {
307 0 : opts := make([]SkillLevelDTO, 0, len(list))
308 0 : for _, sl := range list {
309 0 : label, text, description, descriptionText := sl.Code, sl.Code, sl.Code, sl.Code
310 0 : if resolve != nil {
311 0 : label, text, description, descriptionText = resolve(sl.Code, sl.Code)
312 0 : }
313 0 : opts = append(opts, SkillLevelDTO{
314 0 : ID: sl.ID,
315 0 : Code: sl.Code,
316 0 : Label: label,
317 0 : Description: description,
318 0 : Text: text,
319 0 : DescriptionText: descriptionText,
320 0 : Value: sl.ID,
321 0 : Disabled: false,
322 0 : SortOrder: sl.SortOrder,
323 0 : })
324 : }
325 0 : sort.SliceStable(opts, func(i, j int) bool {
326 0 : if opts[i].SortOrder == opts[j].SortOrder {
327 0 : return opts[i].Code < opts[j].Code
328 0 : }
329 0 : return opts[i].SortOrder < opts[j].SortOrder
330 : })
331 :
332 0 : h := sha1.New()
333 0 : for _, o := range opts {
334 0 : _, _ = h.Write([]byte(o.Code))
335 0 : _, _ = h.Write([]byte{0})
336 0 : }
337 0 : etag := `W/"` + hex.EncodeToString(h.Sum(nil)) + `"`
338 0 : return ListSkillLevelOutput{
339 0 : Items: opts,
340 0 : ETag: etag,
341 0 : }
342 : }
343 :
344 : // assembleExperience は 経験年数のエンティティの配列と [コード+表示名]を解決する関数を受取
345 : // DTOのスライスとETagを組み立てます
346 : func assembleExperience(
347 : list []entity.Experience,
348 : resolve func(code, fallback string) (string, string),
349 0 : ) ListExperienceOutput {
350 0 : opts := make([]ExperienceDTO, 0, len(list))
351 0 : for _, ex := range list {
352 0 : label, text := ex.Code, ex.Code
353 0 : if resolve != nil {
354 0 : label, text = resolve(ex.Code, ex.Code)
355 0 : }
356 0 : opts = append(opts, ExperienceDTO{
357 0 : ID: ex.ID,
358 0 : Code: ex.Code,
359 0 : Label: label,
360 0 : Text: text,
361 0 : Value: ex.ID,
362 0 : Disabled: false,
363 0 : SortOrder: ex.SortOrder,
364 0 : })
365 : }
366 0 : sort.SliceStable(opts, func(i, j int) bool {
367 0 : if opts[i].SortOrder == opts[j].SortOrder {
368 0 : return opts[i].Code < opts[j].Code
369 0 : }
370 0 : return opts[i].SortOrder < opts[j].SortOrder
371 : })
372 :
373 0 : h := sha1.New()
374 0 : for _, o := range opts {
375 0 : _, _ = h.Write([]byte(o.Code))
376 0 : _, _ = h.Write([]byte{0})
377 0 : }
378 0 : etag := `W/"` + hex.EncodeToString(h.Sum(nil)) + `"`
379 0 : return ListExperienceOutput{
380 0 : Items: opts,
381 0 : ETag: etag,
382 0 : }
383 : }
384 :
385 : // assembleRelationshipType は 続柄タイプのエンティティの配列と [コード+表示名]を解決する関数を受取
386 : // DTOのスライスとETagを組み立てます
387 : func assembleRelationshipType(
388 : list []entity.RelationshipType,
389 : resolve func(code, fallback string) (string, string),
390 0 : ) ListRelationshipTypeOutput {
391 0 : opts := make([]RelationshipTypeDTO, 0, len(list))
392 0 : for _, rt := range list {
393 0 : label, text := rt.Code, rt.Code
394 0 : if resolve != nil {
395 0 : label, text = resolve(rt.Code, rt.Code)
396 0 : }
397 0 : opts = append(opts, RelationshipTypeDTO{
398 0 : ID: rt.ID,
399 0 : Code: rt.Code,
400 0 : Label: label,
401 0 : Text: text,
402 0 : Value: rt.ID,
403 0 : Disabled: false,
404 0 : SortOrder: rt.SortOrder,
405 0 : })
406 : }
407 0 : sort.SliceStable(opts, func(i, j int) bool {
408 0 : if opts[i].SortOrder == opts[j].SortOrder {
409 0 : return opts[i].Code < opts[j].Code
410 0 : }
411 0 : return opts[i].SortOrder < opts[j].SortOrder
412 : })
413 0 : h := sha1.New()
414 0 : for _, o := range opts {
415 0 : _, _ = h.Write([]byte(o.Code))
416 0 : _, _ = h.Write([]byte{0})
417 0 : }
418 0 : etag := `W/"` + hex.EncodeToString(h.Sum(nil)) + `"`
419 0 : return ListRelationshipTypeOutput{
420 0 : Items: opts,
421 0 : ETag: etag,
422 0 : }
423 : }
|