1 package bsl
2
3 import (
4 "context"
5 "encoding/json"
6 "fmt"
7 "strconv"
8
9 "edge-infra.dev/pkg/edge/api/graph/model"
10 "edge-infra.dev/pkg/edge/api/utils"
11 "edge-infra.dev/pkg/edge/constants/api/banner"
12
13 corev1 "k8s.io/api/core/v1"
14 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
15
16 "sigs.k8s.io/controller-runtime/pkg/client"
17 )
18
19 const (
20 Active Status = iota
21 Inactive
22
23 Daily Day = iota
24 Monday
25 Tuesday
26 Wednesday
27 Thursday
28 Friday
29 Saturday
30 Sunday
31 )
32
33 type BSLInfo struct {
34 ID string `json:"id"`
35 SiteName string `json:"siteName"`
36 EnterpriseUnitName string `json:"enterpriseUnitName"`
37 Description string `json:"description"`
38 OrganizationID string `json:"organizationID"`
39 OrganizationName string `json:"organizationName"`
40 ParentEnterpriseUnitID string `json:"parentEnterpriseUnitID"`
41 ReferenceID string `json:"referenceID"`
42 Coordinates Coordinates `json:"coordinates"`
43 Address Address `json:"address"`
44 Contact Contact `json:"contact"`
45 Currency string `json:"currency"`
46 DayParts []DayParts `json:"dayparts"`
47 DeactivatedOn string `json:"deactivatedOn"`
48 LastModifiedOn string `json:"lastModifiedOn"`
49 Locked bool `json:"locked"`
50 CustomAttributeSets []CustomAttributeSet `json:"customAttributeSets"`
51 EnterpriseSettings []EnterpriseSetting `json:"enterpriseSettings"`
52 Status string `json:"status"`
53 TimeZone string `json:"timeZone"`
54 Hours []Hours `json:"hours"`
55 CreatedOn string `json:"createdOn"`
56 Endpoint string `json:"endpoint"`
57 Contacts map[string]Contact `json:"contacts"`
58 }
59
60 type BSLOrganization struct {
61 ID string `json:"id"`
62 OrganizationName string `json:"organizationName"`
63 DisplayName string `json:"displayName"`
64 Description string `json:"description"`
65 Parent bool `json:"parent"`
66 }
67
68 type Hours struct {
69 Close SiteHours `json:"close"`
70 Open SiteHours `json:"open"`
71 }
72
73 type SiteHours struct {
74 Day string `json:"day"`
75 Time string `json:"time"`
76 }
77
78 type Coordinates struct {
79 Latitude float64
80 Longitude float64
81 }
82
83 type Address struct {
84 City string
85 Country string
86 PostalCode string
87 State string
88 Street string
89 }
90
91 type Contact struct {
92 ContactPerson string `json:"contactPerson"`
93 Email string `json:"email"`
94 PhoneNumber string `json:"phoneNumber"`
95 PhoneNumberCountryCode string `json:"phoneNumberCountryCode"`
96 }
97
98 type CustomAttributeSet struct {
99 TypeName string
100 Attributes []Attribute
101 }
102
103 type Attribute struct {
104 Key string
105 Value string
106 }
107
108 type DayParts struct {
109 Name string
110 Description string
111 Day string
112 StartTime string
113 EndTime string
114 }
115
116 type Day int
117
118 type Status int
119
120 type EnterpriseSetting struct {
121 EnterpriseUnitID string
122 ConfigurationSetID ConfigurationSetID
123 ConfigurationSettings []ConfigurationSetting
124 }
125
126 type ConfigurationSetID struct {
127 Name string
128 }
129
130 type ConfigurationSetting struct {
131 Key string
132 Value string
133 }
134
135
136 func (s Status) String() string {
137 switch s {
138 case Active:
139 return "ACTIVE"
140 case Inactive:
141 return "INACTIVE"
142 default:
143 return "ACTIVE"
144 }
145 }
146
147
148 func (d Day) String() string {
149 switch d {
150 case Daily:
151 return "DAILY"
152 case Monday:
153 return "MONDAY"
154 case Tuesday:
155 return "TUESDAY"
156 case Wednesday:
157 return "WEDNESDAY"
158 case Thursday:
159 return "THURSDAY"
160 case Friday:
161 return "FRIDAY"
162 case Saturday:
163 return "SATURDAY"
164 case Sunday:
165 return "SUNDAY"
166 default:
167 return "DAILY"
168 }
169 }
170
171 func NewBSLInfo() *BSLInfo {
172 return &BSLInfo{Contacts: make(map[string]Contact)}
173 }
174
175
176 func (b *BSLInfo) SetID(id string) *BSLInfo {
177 b.ID = id
178 return b
179 }
180
181
182 func (b *BSLInfo) SetSiteName(siteName string) *BSLInfo {
183 b.SiteName = siteName
184 return b
185 }
186
187
188 func (b *BSLInfo) SetEnterpriseUnitName(enterpriseUnitName string) *BSLInfo {
189 b.EnterpriseUnitName = enterpriseUnitName
190 return b
191 }
192
193
194 func (b *BSLInfo) SetLatitude(latitude float64) *BSLInfo {
195 b.Coordinates.Latitude = latitude
196 return b
197 }
198
199
200 func (b *BSLInfo) SetLongitude(longitude float64) *BSLInfo {
201 b.Coordinates.Longitude = longitude
202 return b
203 }
204
205
206 func (b *BSLInfo) SetAddress(street, city, state, country, postalCode string) *BSLInfo {
207 b.Address.Street = street
208 b.Address.City = city
209 b.Address.State = state
210 b.Address.Country = country
211 b.Address.PostalCode = postalCode
212 return b
213 }
214
215
216 func (b *BSLInfo) SetContact(contactPerson, phoneNumber, phoneNumberCountryCode string) *BSLInfo {
217 b.Contact.ContactPerson = contactPerson
218 b.Contact.PhoneNumber = phoneNumber
219 b.Contact.PhoneNumberCountryCode = phoneNumberCountryCode
220 return b
221 }
222
223
224 func (b *BSLInfo) SetCustomAttributes(customAttributes []CustomAttributeSet) *BSLInfo {
225 b.CustomAttributeSets = customAttributes
226 return b
227 }
228
229
230 func (b *BSLInfo) AddCustomAttributes(customAttributes []CustomAttributeSet) *BSLInfo {
231 b.CustomAttributeSets = append(b.CustomAttributeSets, customAttributes...)
232 return b
233 }
234
235
236
237 func (b *BSLInfo) AddAttributeToCustomAttributeSet(typeName string, attribute Attribute) *BSLInfo {
238 for i := 0; i < len(b.CustomAttributeSets); i++ {
239 if b.CustomAttributeSets[i].TypeName == typeName {
240 b.CustomAttributeSets[i].Attributes = append(b.CustomAttributeSets[i].Attributes, attribute)
241 }
242 }
243 return b
244 }
245
246
247 func (b *BSLInfo) SetCurrency(currency string) *BSLInfo {
248 b.Currency = currency
249 return b
250 }
251
252
253 func (b *BSLInfo) SetCreatedOn(createdOn string) *BSLInfo {
254 b.CreatedOn = createdOn
255 return b
256 }
257
258
259 func (b *BSLInfo) SetDescription(description string) *BSLInfo {
260 b.Description = description
261 return b
262 }
263
264
265 func (b *BSLInfo) SetEnterpriseSettings(enterpriseSettings []EnterpriseSetting) *BSLInfo {
266 b.EnterpriseSettings = enterpriseSettings
267 return b
268 }
269
270
271
272 func (b *BSLInfo) AddEnterpriseSetting(enterpriseSetting EnterpriseSetting) *BSLInfo {
273 b.EnterpriseSettings = append(b.EnterpriseSettings, enterpriseSetting)
274 return b
275 }
276
277
278
279 func (b *BSLInfo) AddEnterpriseConfigurationSetting(enterpriseUnitID string, enterpriseConfigurationSetting ConfigurationSetting) *BSLInfo {
280 for i := 0; i < len(b.EnterpriseSettings); i++ {
281 if b.EnterpriseSettings[i].EnterpriseUnitID == enterpriseUnitID {
282 b.EnterpriseSettings[i].ConfigurationSettings = append(b.EnterpriseSettings[i].ConfigurationSettings, enterpriseConfigurationSetting)
283 }
284 }
285 return b
286 }
287
288
289 func (b *BSLInfo) SetLastModifiedOn(lastModifiedOn string) *BSLInfo {
290 b.LastModifiedOn = lastModifiedOn
291 return b
292 }
293
294
295 func (b *BSLInfo) SetLocked(locked bool) *BSLInfo {
296 b.Locked = locked
297 return b
298 }
299
300
301 func (b *BSLInfo) SetStatus(status Status) *BSLInfo {
302 b.Status = status.String()
303 return b
304 }
305
306
307 func (b *BSLInfo) SetDayparts(name, description, startTime, endTime, day string) *BSLInfo {
308 b.DayParts = append(b.DayParts, DayParts{
309 Name: name,
310 Description: description,
311 Day: day,
312 StartTime: startTime,
313 EndTime: endTime,
314 })
315 return b
316 }
317
318
319 func (b *BSLInfo) SetOrganizationName(organizationName string) *BSLInfo {
320 b.OrganizationName = organizationName
321 return b
322 }
323
324
325 func (b *BSLInfo) SetParentEnterpriseUnitID(parentEnterpriseUnitID string) *BSLInfo {
326 b.ParentEnterpriseUnitID = parentEnterpriseUnitID
327 return b
328 }
329
330
331 func (b *BSLInfo) SetReferenceID(referenceID string) *BSLInfo {
332 b.ReferenceID = referenceID
333 return b
334 }
335
336
337 func (b *BSLInfo) SetTimeZone(timeZone string) *BSLInfo {
338 b.TimeZone = timeZone
339 return b
340 }
341
342
343 func (b *BSLInfo) SetHours(openDay, openTime, closeDay, closeTime string) *BSLInfo {
344 b.Hours = append(b.Hours, Hours{
345 Close: SiteHours{
346 Day: closeDay,
347 Time: closeTime,
348 },
349 Open: SiteHours{
350 Day: openDay,
351 Time: openTime,
352 },
353 })
354 return b
355 }
356
357 func (b *BSLInfo) SetEndpoint(endpoint string) *BSLInfo {
358 b.Endpoint = endpoint
359 return b
360 }
361
362
363 func (b *BSLInfo) LockedToString() string {
364 return strconv.FormatBool(b.Locked)
365 }
366
367
368 func (b *BSLInfo) CoordinateLatitudeToString() string {
369 return convertFloatToString(b.Coordinates.Latitude)
370 }
371
372
373 func (b *BSLInfo) CoordinateLongitdeToString() string {
374 return convertFloatToString(b.Coordinates.Longitude)
375 }
376
377
378
379 func (b *BSLInfo) DaypartsToString() string {
380 if b.DayParts == nil {
381 b.DayParts = []DayParts{}
382 }
383
384 result, err := json.Marshal(b.DayParts)
385 if err != nil {
386 return "[]"
387 }
388 return string(result)
389 }
390
391 func (b *BSLInfo) ContactsToString() string {
392 if b.Contacts == nil {
393 b.Contacts = make(map[string]Contact, 0)
394 }
395 result, err := json.Marshal(b.Contacts)
396 if err != nil {
397 return "{}"
398 }
399 return string(result)
400 }
401
402
403
404 func (b *BSLInfo) CustomAttributeSetsToString() string {
405 if b.CustomAttributeSets == nil {
406 b.CustomAttributeSets = []CustomAttributeSet{}
407 }
408
409 result, err := json.Marshal(b.CustomAttributeSets)
410 if err != nil {
411 return "[]"
412 }
413 return string(result)
414 }
415
416
417
418 func (b *BSLInfo) EnterpriseSettingsToString() string {
419 if b.EnterpriseSettings == nil {
420 b.EnterpriseSettings = []EnterpriseSetting{}
421 }
422
423 result, err := json.Marshal(b.EnterpriseSettings)
424 if err != nil {
425 return "[]"
426 }
427 return string(result)
428 }
429
430
431 func (b *BSLInfo) HoursToString() string {
432 if b.Hours == nil {
433 b.Hours = []Hours{}
434 }
435
436 result, err := json.Marshal(b.Hours)
437 if err != nil {
438 return "[]"
439 }
440 return string(result)
441 }
442
443 func (b *BSLInfo) AddBSLOrgID(sqlBanner *model.Banner, sqlTenant *model.Tenant) *BSLInfo {
444 b.OrganizationID = sqlBanner.BannerBSLId
445 if sqlBanner.BannerType == string(banner.EU) {
446 b.OrganizationID = sqlTenant.TenantBSLId
447 }
448 return b
449 }
450
451
452 func (b *BSLInfo) NewBSLInfoConfigMap() *corev1.ConfigMap {
453 return &corev1.ConfigMap{
454 TypeMeta: metav1.TypeMeta{
455 Kind: "ConfigMap",
456 APIVersion: "v1",
457 },
458 ObjectMeta: metav1.ObjectMeta{
459 Name: BSLInfoConfigMapName,
460 Namespace: metav1.NamespacePublic,
461 },
462 Data: map[string]string{
463 BSLSiteID: b.ID,
464 BSLSiteName: b.SiteName,
465 BSLSiteEnterpriseUnitName: b.EnterpriseUnitName,
466 BSLSiteDescription: b.Description,
467 BSLOrganizationID: b.OrganizationID,
468 BSLSiteOrganizationName: b.OrganizationName,
469 BSLSiteParentEnterpriseUnitID: b.ParentEnterpriseUnitID,
470 BSLSiteReferenceID: b.ReferenceID,
471 BSLSiteCoordinateLatitude: b.CoordinateLatitudeToString(),
472 BSLSiteCoordinateLongitude: b.CoordinateLongitdeToString(),
473 BSLSiteAddressStreet: b.Address.Street,
474 BSLSiteAddressCity: b.Address.City,
475 BSLSiteAddressState: b.Address.State,
476 BSLSiteAddressCountry: b.Address.Country,
477 BSLSiteAddressPostalCode: b.Address.PostalCode,
478 BSLSiteContactPerson: b.Contact.ContactPerson,
479 BSLSiteContactPhoneNumber: b.Contact.PhoneNumber,
480 BSLSiteContactPhoneNumberCountryCode: b.Contact.PhoneNumberCountryCode,
481 BSLSiteCurrency: b.Currency,
482 BSLSiteDayParts: b.DaypartsToString(),
483 BSLSiteDeactivatedOn: b.DeactivatedOn,
484 BSLSiteLastModifiedOn: b.LastModifiedOn,
485 BSLSiteLocked: b.LockedToString(),
486 BSLSiteCustomAttributeSets: b.CustomAttributeSetsToString(),
487 BSLSiteEnterpriseSettings: b.EnterpriseSettingsToString(),
488 BSLSiteStatus: b.Status,
489 BSLSiteTimeZone: b.TimeZone,
490 BSLSiteHours: b.HoursToString(),
491 BSLSiteCreatedOn: b.CreatedOn,
492 BSLEndpoint: b.Endpoint,
493 BSLSiteContacts: b.ContactsToString(),
494 },
495 }
496 }
497
498 func (b *BSLInfo) FromConfigMap(cfg *corev1.ConfigMap) (*BSLInfo, error) {
499 b.ID = cfg.Data[BSLSiteID]
500 b.SiteName = cfg.Data[BSLSiteName]
501 b.EnterpriseUnitName = cfg.Data[BSLSiteEnterpriseUnitName]
502 b.Description = cfg.Data[BSLSiteDescription]
503 b.OrganizationID = cfg.Data[BSLOrganizationID]
504 b.OrganizationName = cfg.Data[BSLSiteOrganizationName]
505 b.ParentEnterpriseUnitID = cfg.Data[BSLSiteParentEnterpriseUnitID]
506 b.ReferenceID = cfg.Data[BSLSiteReferenceID]
507 b.Endpoint = cfg.Data[BSLEndpoint]
508
509 lat, err := strconv.ParseFloat(cfg.Data[BSLSiteCoordinateLatitude], 64)
510 if err != nil {
511 return nil, err
512 }
513
514 lng, err := strconv.ParseFloat(cfg.Data[BSLSiteCoordinateLongitude], 64)
515 if err != nil {
516 return nil, err
517 }
518
519 b.Coordinates = Coordinates{
520 Latitude: lat,
521 Longitude: lng,
522 }
523
524 b.Address = Address{
525 City: cfg.Data[BSLSiteAddressCity],
526 Country: cfg.Data[BSLSiteAddressCountry],
527 PostalCode: cfg.Data[BSLSiteAddressPostalCode],
528 State: cfg.Data[BSLSiteAddressState],
529 Street: cfg.Data[BSLSiteAddressStreet],
530 }
531 b.Contact = Contact{
532 ContactPerson: cfg.Data[BSLSiteContactPerson],
533 Email: cfg.Data[BSLSiteContactEmail],
534 PhoneNumber: cfg.Data[BSLSiteContactPhoneNumber],
535 PhoneNumberCountryCode: cfg.Data[BSLSiteContactPhoneNumberCountryCode],
536 }
537 b.Contacts = make(map[string]Contact, 0)
538 err = fromJSONString(cfg.Data[BSLSiteContacts], &b.Contacts)
539 if err != nil {
540 return nil, err
541 }
542 b.Currency = cfg.Data[BSLSiteCurrency]
543
544 b.DayParts = make([]DayParts, 0)
545 err = fromJSONString(cfg.Data[BSLSiteDayParts], &b.DayParts)
546 if err != nil {
547 return nil, err
548 }
549
550 b.DeactivatedOn = cfg.Data[BSLSiteDeactivatedOn]
551 b.LastModifiedOn = cfg.Data[BSLSiteLastModifiedOn]
552
553
554 locked, err := strconv.ParseBool(cfg.Data[BSLSiteLocked])
555 if err != nil {
556 return nil, err
557 }
558 b.Locked = locked
559
560 b.CustomAttributeSets = make([]CustomAttributeSet, 0)
561 err = fromJSONString(cfg.Data[BSLSiteCustomAttributeSets], &b.CustomAttributeSets)
562 if err != nil {
563 return nil, err
564 }
565
566 b.EnterpriseSettings = make([]EnterpriseSetting, 0)
567 err = fromJSONString(cfg.Data[BSLSiteEnterpriseSettings], &b.EnterpriseSettings)
568 if err != nil {
569 return nil, err
570 }
571
572 b.Status = cfg.Data[BSLSiteStatus]
573 b.TimeZone = cfg.Data[BSLSiteTimeZone]
574
575 b.Hours = make([]Hours, 0)
576 err = fromJSONString(cfg.Data[BSLSiteHours], &b.Hours)
577 if err != nil {
578 return nil, err
579 }
580
581 b.CreatedOn = cfg.Data[BSLSiteCreatedOn]
582 return b, nil
583 }
584
585
586 func FromConfigMap(cfg *corev1.ConfigMap) (*BSLInfo, error) {
587 return (&BSLInfo{}).FromConfigMap(cfg)
588 }
589
590
591 func FromClient(ctx context.Context, cl client.Client) (*BSLInfo, error) {
592 cfg := &corev1.ConfigMap{}
593 key := client.ObjectKey{Namespace: metav1.NamespacePublic, Name: BSLInfoConfigMapName}
594 if err := cl.Get(ctx, key, cfg); err != nil {
595 return nil, err
596 }
597 return FromConfigMap(cfg)
598 }
599
600
601 func IsBslInfoConfigMap(name, namespace string) bool {
602 hasRequiredName := name == BSLInfoConfigMapName
603 inRequiredNamespace := namespace == metav1.NamespacePublic
604 return hasRequiredName && inRequiredNamespace
605 }
606
607 func fromJSONString(data string, v interface{}) error {
608 return json.Unmarshal([]byte(data), v)
609 }
610
611 func AddOrganizationID(organizationID string, c *corev1.ConfigMap) *corev1.ConfigMap {
612 c.Data[BSLOrganizationID] = organizationID
613 return c
614 }
615
616
617 func BuildConfigMap(siteName, enterpriseUnitName, organizationName string, latitude, longitude float64, siteID *string) *corev1.ConfigMap {
618 bslInfo := &BSLInfo{}
619 bslInfo.SetSiteName(siteName).
620 SetEnterpriseUnitName(enterpriseUnitName).
621 SetOrganizationName(organizationName).
622 SetStatus(Active).
623 SetLatitude(latitude).
624 SetLongitude(longitude)
625 if !utils.IsNullOrEmpty(siteID) {
626 bslInfo.SetID(*siteID)
627 }
628 return bslInfo.NewBSLInfoConfigMap()
629 }
630
631
632 func ConfigMapToString(configMap *corev1.ConfigMap) (string, error) {
633 marshalled, err := json.Marshal(configMap)
634 if err != nil {
635 return "", err
636 }
637 return utils.ToBase64(marshalled), nil
638 }
639
640
641 func convertFloatToString(value float64) string {
642 return fmt.Sprintf("%f", value)
643 }
644
View as plain text