Initial work marking communications

And a bunch of lint fixes
This commit is contained in:
Eli Ribble 2026-05-04 19:07:29 +00:00
parent 67c99436d1
commit 3153e8bf13
No known key found for this signature in database
36 changed files with 1958 additions and 487 deletions

View file

@ -230,7 +230,12 @@ func webhookFieldseeker(w http.ResponseWriter, r *http.Request) {
// Write timestamp // Write timestamp
timestamp := time.Now().Format("2006-01-02 15:04:05") timestamp := time.Now().Format("2006-01-02 15:04:05")
fmt.Fprintf(file, "\n=== Request logged at %s ===\n", timestamp) _, err = fmt.Fprintf(file, "\n=== Request logged at %s ===\n", timestamp)
if err != nil {
log.Error().Err(err).Msg("writing response")
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
// Write request line // Write request line
fmt.Fprintf(file, "%s %s %s\n", r.Method, r.RequestURI, r.Proto) fmt.Fprintf(file, "%s %s %s\n", r.Method, r.RequestURI, r.Proto)
@ -250,7 +255,13 @@ func webhookFieldseeker(w http.ResponseWriter, r *http.Request) {
log.Printf("Error reading request body: %v", err) log.Printf("Error reading request body: %v", err)
fmt.Fprintf(file, "Error reading body: %v\n", err) fmt.Fprintf(file, "Error reading body: %v\n", err)
} else { } else {
file.Write(body) _, err = file.Write(body)
if err != nil {
log.Error().Err(err).Msg("writing response")
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
if len(body) == 0 { if len(body) == 0 {
fmt.Fprintf(file, "(empty body)") fmt.Fprintf(file, "(empty body)")
} }

View file

@ -69,6 +69,7 @@ func apiAudioContentPost(w http.ResponseWriter, r *http.Request, user platform.U
if err != nil { if err != nil {
log.Printf("Failed to write content file: %v", err) log.Printf("Failed to write content file: %v", err)
http.Error(w, "failed to write content file", http.StatusInternalServerError) http.Error(w, "failed to write content file", http.StatusInternalServerError)
return
} }
ctx := r.Context() ctx := r.Context()
a, err := models.NoteAudios.Query( a, err := models.NoteAudios.Query(
@ -78,8 +79,15 @@ func apiAudioContentPost(w http.ResponseWriter, r *http.Request, user platform.U
if err != nil { if err != nil {
log.Printf("Failed to get note audio %s for org %d: %w", u_str, user.Organization.ID, err) log.Printf("Failed to get note audio %s for org %d: %w", u_str, user.Organization.ID, err)
http.Error(w, "failed to update database", http.StatusBadRequest) http.Error(w, "failed to update database", http.StatusBadRequest)
return
}
err = background.NewAudioTranscode(ctx, db.PGInstance.BobDB, a.ID)
if err != nil {
log.Printf("Failed to transcode audio %s for org %d: %w", u_str, user.Organization.ID, err)
http.Error(w, "failed to transcode audio", http.StatusBadRequest)
return
} }
background.NewAudioTranscode(ctx, db.PGInstance.BobDB, a.ID)
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
} }

View file

@ -5,6 +5,7 @@ import (
"net/http" "net/http"
"os" "os"
"github.com/Gleipnir-Technology/nidus-sync/lint"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
@ -14,7 +15,7 @@ func debugSaveRequest(r *http.Request) {
log.Error().Err(err).Msg("failed to create temp file for debugSaveRequest") log.Error().Err(err).Msg("failed to create temp file for debugSaveRequest")
return return
} }
defer tmpFile.Close() defer lint.LogOnErr(tmpFile.Close, "close temp file")
_, err = io.Copy(tmpFile, r.Body) _, err = io.Copy(tmpFile, r.Body)
if err != nil { if err != nil {

View file

@ -30,7 +30,7 @@ type handlerFunctionGet[T any] func(context.Context, *http.Request, resource.Que
type handlerFunctionGetAuthenticated[T any] func(context.Context, *http.Request, platform.User, resource.QueryParams) (*T, *nhttp.ErrorWithStatus) type handlerFunctionGetAuthenticated[T any] func(context.Context, *http.Request, platform.User, resource.QueryParams) (*T, *nhttp.ErrorWithStatus)
type handlerFunctionGetImage func(context.Context, *http.Request, platform.User) (file.Collection, uuid.UUID, *nhttp.ErrorWithStatus) type handlerFunctionGetImage func(context.Context, *http.Request, platform.User) (file.Collection, uuid.UUID, *nhttp.ErrorWithStatus)
type handlerFunctionGetSlice[T any] func(context.Context, *http.Request, resource.QueryParams) ([]*T, *nhttp.ErrorWithStatus) type handlerFunctionGetSlice[T any] func(context.Context, *http.Request, resource.QueryParams) ([]*T, *nhttp.ErrorWithStatus)
type handlerFunctionGetSliceAuthenticated[T any] func(context.Context, *http.Request, platform.User, resource.QueryParams) ([]*T, *nhttp.ErrorWithStatus) type handlerFunctionGetSliceAuthenticated[T any] func(context.Context, *http.Request, platform.User, resource.QueryParams) ([]T, *nhttp.ErrorWithStatus)
type handlerFunctionPost[RequestType any, ResponseType any] func(context.Context, *http.Request, RequestType) (ResponseType, *nhttp.ErrorWithStatus) type handlerFunctionPost[RequestType any, ResponseType any] func(context.Context, *http.Request, RequestType) (ResponseType, *nhttp.ErrorWithStatus)
type handlerFunctionPostAuthenticated[RequestType any, ResponseType any] func(context.Context, *http.Request, platform.User, RequestType) (ResponseType, *nhttp.ErrorWithStatus) type handlerFunctionPostAuthenticated[RequestType any, ResponseType any] func(context.Context, *http.Request, platform.User, RequestType) (ResponseType, *nhttp.ErrorWithStatus)
type handlerFunctionPostFormMultipart[RequestType any, ResponseType any] func(context.Context, *http.Request, RequestType) (*ResponseType, *nhttp.ErrorWithStatus) type handlerFunctionPostFormMultipart[RequestType any, ResponseType any] func(context.Context, *http.Request, RequestType) (*ResponseType, *nhttp.ErrorWithStatus)

View file

@ -99,6 +99,11 @@ func AddRoutesSync(r *mux.Router) {
r.Handle("/client/ios", auth.NewEnsureAuth(handleClientIos)).Methods("GET") r.Handle("/client/ios", auth.NewEnsureAuth(handleClientIos)).Methods("GET")
communication := resource.Communication(router) communication := resource.Communication(router)
r.Handle("/communication", authenticatedHandlerJSONSlice(communication.List)).Methods("GET") r.Handle("/communication", authenticatedHandlerJSONSlice(communication.List)).Methods("GET")
r.Handle("/communication/{id}", authenticatedHandlerJSON(communication.Get)).Methods("GET").Name("communication.ByIDGet")
r.Handle("/communication/{id}/mark/invalid", authenticatedHandlerJSONPost(communication.MarkInvalid)).Methods("GET").Name("communication.MarkInvalid")
r.Handle("/communication/{id}/mark/pending-response", authenticatedHandlerJSONPost(communication.MarkPendingResponse)).Methods("GET").Name("communication.MarkPendingResponse")
r.Handle("/communication/{id}/mark/possible-issue", authenticatedHandlerJSONPost(communication.MarkPossibleIssue)).Methods("GET").Name("communication.MarkPossibleIssue")
r.Handle("/communication/{id}/mark/possible-resolved", authenticatedHandlerJSONPost(communication.MarkPossibleResolved)).Methods("GET").Name("communication.MarkPossibleResolved")
r.Handle("/compliance-request/mailer", authenticatedHandlerJSONPost(compliance_request.CreateMailer)).Methods("POST") r.Handle("/compliance-request/mailer", authenticatedHandlerJSONPost(compliance_request.CreateMailer)).Methods("POST")
//r.HandleFunc("/compliance-request/image/pool/{public_id}", getComplianceRequestImagePool).Methods("GET") //r.HandleFunc("/compliance-request/image/pool/{public_id}", getComplianceRequestImagePool).Methods("GET")
r.Handle("/configuration/integration/arcgis", authenticatedHandlerJSONPost(postConfigurationIntegrationArcgis)).Methods("POST") r.Handle("/configuration/integration/arcgis", authenticatedHandlerJSONPost(postConfigurationIntegrationArcgis)).Methods("POST")

View file

@ -143,7 +143,10 @@ func (ea *EnsureAuth) ServeHTTP(w http.ResponseWriter, r *http.Request) {
} }
w.WriteHeader(401) w.WriteHeader(401)
w.Write(msg) _, err = w.Write(msg)
if err != nil {
log.Error().Err(err).Msg("failed to write response")
}
return return
} }
ea.handler(w, r, *user) ea.handler(w, r, *user)

View file

@ -5,12 +5,13 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io/ioutil" "io"
"net/http" "net/http"
"net/url" "net/url"
"strconv" "strconv"
"github.com/Gleipnir-Technology/nidus-sync/config" "github.com/Gleipnir-Technology/nidus-sync/config"
"github.com/Gleipnir-Technology/nidus-sync/lint"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
@ -87,10 +88,10 @@ func makeVoipMSRequest(params url.Values) (VoipMSResponse, error) {
log.Warn().Err(err).Str("url", full_url).Msg("Failed to make request to Voip.MS") log.Warn().Err(err).Str("url", full_url).Msg("Failed to make request to Voip.MS")
return result, fmt.Errorf("Error making request: %w", err) return result, fmt.Errorf("Error making request: %w", err)
} }
defer resp.Body.Close() defer lint.LogOnErr(resp.Body.Close, "failed closing response body")
// Read the response body // Read the response body
body, err := ioutil.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
log.Warn().Err(err).Str("url", full_url).Msg("Failed to read Voip.MS response body") log.Warn().Err(err).Str("url", full_url).Msg("Failed to read Voip.MS response body")
return result, fmt.Errorf("Failed to read response: %w", err) return result, fmt.Errorf("Failed to read response: %w", err)

View file

@ -87,6 +87,15 @@ var Communications = Table[
Generated: false, Generated: false,
AutoIncr: false, AutoIncr: false,
}, },
OrganizationID: column{
Name: "organization_id",
DBType: "integer",
Default: "",
Comment: "",
Nullable: false,
Generated: false,
AutoIncr: false,
},
ResponseEmailLogID: column{ ResponseEmailLogID: column{
Name: "response_email_log_id", Name: "response_email_log_id",
DBType: "integer", DBType: "integer",
@ -150,6 +159,42 @@ var Communications = Table[
Generated: false, Generated: false,
AutoIncr: false, AutoIncr: false,
}, },
SetPossibleIssue: column{
Name: "set_possible_issue",
DBType: "timestamp without time zone",
Default: "NULL",
Comment: "",
Nullable: true,
Generated: false,
AutoIncr: false,
},
SetPossibleIssueBy: column{
Name: "set_possible_issue_by",
DBType: "integer",
Default: "NULL",
Comment: "",
Nullable: true,
Generated: false,
AutoIncr: false,
},
SetPossibleResolved: column{
Name: "set_possible_resolved",
DBType: "timestamp without time zone",
Default: "NULL",
Comment: "",
Nullable: true,
Generated: false,
AutoIncr: false,
},
SetPossibleResolvedBy: column{
Name: "set_possible_resolved_by",
DBType: "integer",
Default: "NULL",
Comment: "",
Nullable: true,
Generated: false,
AutoIncr: false,
},
}, },
Indexes: communicationIndexes{ Indexes: communicationIndexes{
CommunicationPkey: index{ CommunicationPkey: index{
@ -203,6 +248,15 @@ var Communications = Table[
ForeignTable: "user_", ForeignTable: "user_",
ForeignColumns: []string{"id"}, ForeignColumns: []string{"id"},
}, },
CommunicationCommunicationOrganizationIDFkey: foreignKey{
constraint: constraint{
Name: "communication.communication_organization_id_fkey",
Columns: []string{"organization_id"},
Comment: "",
},
ForeignTable: "organization",
ForeignColumns: []string{"id"},
},
CommunicationCommunicationResponseEmailLogIDFkey: foreignKey{ CommunicationCommunicationResponseEmailLogIDFkey: foreignKey{
constraint: constraint{ constraint: constraint{
Name: "communication.communication_response_email_log_id_fkey", Name: "communication.communication_response_email_log_id_fkey",
@ -230,6 +284,24 @@ var Communications = Table[
ForeignTable: "user_", ForeignTable: "user_",
ForeignColumns: []string{"id"}, ForeignColumns: []string{"id"},
}, },
CommunicationCommunicationSetPossibleIssueByFkey: foreignKey{
constraint: constraint{
Name: "communication.communication_set_possible_issue_by_fkey",
Columns: []string{"set_possible_issue_by"},
Comment: "",
},
ForeignTable: "user_",
ForeignColumns: []string{"id"},
},
CommunicationCommunicationSetPossibleResolvedByFkey: foreignKey{
constraint: constraint{
Name: "communication.communication_set_possible_resolved_by_fkey",
Columns: []string{"set_possible_resolved_by"},
Comment: "",
},
ForeignTable: "user_",
ForeignColumns: []string{"id"},
},
CommunicationCommunicationSourceEmailLogIDFkey: foreignKey{ CommunicationCommunicationSourceEmailLogIDFkey: foreignKey{
constraint: constraint{ constraint: constraint{
Name: "communication.communication_source_email_log_id_fkey", Name: "communication.communication_source_email_log_id_fkey",
@ -271,6 +343,7 @@ type communicationColumns struct {
InvalidatedBy column InvalidatedBy column
Opened column Opened column
OpenedBy column OpenedBy column
OrganizationID column
ResponseEmailLogID column ResponseEmailLogID column
ResponseTextLogID column ResponseTextLogID column
SetPending column SetPending column
@ -278,11 +351,15 @@ type communicationColumns struct {
SourceEmailLogID column SourceEmailLogID column
SourceReportID column SourceReportID column
SourceTextLogID column SourceTextLogID column
SetPossibleIssue column
SetPossibleIssueBy column
SetPossibleResolved column
SetPossibleResolvedBy column
} }
func (c communicationColumns) AsSlice() []column { func (c communicationColumns) AsSlice() []column {
return []column{ return []column{
c.Closed, c.ClosedBy, c.Created, c.ID, c.Invalidated, c.InvalidatedBy, c.Opened, c.OpenedBy, c.ResponseEmailLogID, c.ResponseTextLogID, c.SetPending, c.SetPendingBy, c.SourceEmailLogID, c.SourceReportID, c.SourceTextLogID, c.Closed, c.ClosedBy, c.Created, c.ID, c.Invalidated, c.InvalidatedBy, c.Opened, c.OpenedBy, c.OrganizationID, c.ResponseEmailLogID, c.ResponseTextLogID, c.SetPending, c.SetPendingBy, c.SourceEmailLogID, c.SourceReportID, c.SourceTextLogID, c.SetPossibleIssue, c.SetPossibleIssueBy, c.SetPossibleResolved, c.SetPossibleResolvedBy,
} }
} }
@ -300,9 +377,12 @@ type communicationForeignKeys struct {
CommunicationCommunicationClosedByFkey foreignKey CommunicationCommunicationClosedByFkey foreignKey
CommunicationCommunicationInvalidatedByFkey foreignKey CommunicationCommunicationInvalidatedByFkey foreignKey
CommunicationCommunicationOpenedByFkey foreignKey CommunicationCommunicationOpenedByFkey foreignKey
CommunicationCommunicationOrganizationIDFkey foreignKey
CommunicationCommunicationResponseEmailLogIDFkey foreignKey CommunicationCommunicationResponseEmailLogIDFkey foreignKey
CommunicationCommunicationResponseTextLogIDFkey foreignKey CommunicationCommunicationResponseTextLogIDFkey foreignKey
CommunicationCommunicationSetPendingByFkey foreignKey CommunicationCommunicationSetPendingByFkey foreignKey
CommunicationCommunicationSetPossibleIssueByFkey foreignKey
CommunicationCommunicationSetPossibleResolvedByFkey foreignKey
CommunicationCommunicationSourceEmailLogIDFkey foreignKey CommunicationCommunicationSourceEmailLogIDFkey foreignKey
CommunicationCommunicationSourceReportIDFkey foreignKey CommunicationCommunicationSourceReportIDFkey foreignKey
CommunicationCommunicationSourceTextLogIDFkey foreignKey CommunicationCommunicationSourceTextLogIDFkey foreignKey
@ -310,7 +390,7 @@ type communicationForeignKeys struct {
func (f communicationForeignKeys) AsSlice() []foreignKey { func (f communicationForeignKeys) AsSlice() []foreignKey {
return []foreignKey{ return []foreignKey{
f.CommunicationCommunicationClosedByFkey, f.CommunicationCommunicationInvalidatedByFkey, f.CommunicationCommunicationOpenedByFkey, f.CommunicationCommunicationResponseEmailLogIDFkey, f.CommunicationCommunicationResponseTextLogIDFkey, f.CommunicationCommunicationSetPendingByFkey, f.CommunicationCommunicationSourceEmailLogIDFkey, f.CommunicationCommunicationSourceReportIDFkey, f.CommunicationCommunicationSourceTextLogIDFkey, f.CommunicationCommunicationClosedByFkey, f.CommunicationCommunicationInvalidatedByFkey, f.CommunicationCommunicationOpenedByFkey, f.CommunicationCommunicationOrganizationIDFkey, f.CommunicationCommunicationResponseEmailLogIDFkey, f.CommunicationCommunicationResponseTextLogIDFkey, f.CommunicationCommunicationSetPendingByFkey, f.CommunicationCommunicationSetPossibleIssueByFkey, f.CommunicationCommunicationSetPossibleResolvedByFkey, f.CommunicationCommunicationSourceEmailLogIDFkey, f.CommunicationCommunicationSourceReportIDFkey, f.CommunicationCommunicationSourceTextLogIDFkey,
} }
} }

View file

@ -62,7 +62,7 @@ var PublicreportCompliances = Table[
}, },
PermissionType: column{ PermissionType: column{
Name: "permission_type", Name: "permission_type",
DBType: "public.permissionaccesstype", DBType: "publicreport.permissionaccesstype",
Default: "", Default: "",
Comment: "", Comment: "",
Nullable: false, Nullable: false,

View file

@ -1283,85 +1283,6 @@ func (e *Notificationtype) Scan(value any) error {
return nil return nil
} }
// Enum values for Permissionaccesstype
const (
PermissionaccesstypeDenied Permissionaccesstype = "denied"
PermissionaccesstypeGranted Permissionaccesstype = "granted"
PermissionaccesstypeUnselected Permissionaccesstype = "unselected"
PermissionaccesstypeWithOwner Permissionaccesstype = "with-owner"
)
func AllPermissionaccesstype() []Permissionaccesstype {
return []Permissionaccesstype{
PermissionaccesstypeDenied,
PermissionaccesstypeGranted,
PermissionaccesstypeUnselected,
PermissionaccesstypeWithOwner,
}
}
type Permissionaccesstype string
func (e Permissionaccesstype) String() string {
return string(e)
}
func (e Permissionaccesstype) Valid() bool {
switch e {
case PermissionaccesstypeDenied,
PermissionaccesstypeGranted,
PermissionaccesstypeUnselected,
PermissionaccesstypeWithOwner:
return true
default:
return false
}
}
// useful when testing in other packages
func (e Permissionaccesstype) All() []Permissionaccesstype {
return AllPermissionaccesstype()
}
func (e Permissionaccesstype) MarshalText() ([]byte, error) {
return []byte(e), nil
}
func (e *Permissionaccesstype) UnmarshalText(text []byte) error {
return e.Scan(text)
}
func (e Permissionaccesstype) MarshalBinary() ([]byte, error) {
return []byte(e), nil
}
func (e *Permissionaccesstype) UnmarshalBinary(data []byte) error {
return e.Scan(data)
}
func (e Permissionaccesstype) Value() (driver.Value, error) {
return string(e), nil
}
func (e *Permissionaccesstype) Scan(value any) error {
switch x := value.(type) {
case string:
*e = Permissionaccesstype(x)
case []byte:
*e = Permissionaccesstype(x)
case nil:
return fmt.Errorf("cannot nil into Permissionaccesstype")
default:
return fmt.Errorf("cannot scan type %T: %v", value, value)
}
if !e.Valid() {
return fmt.Errorf("invalid Permissionaccesstype value: %s", *e)
}
return nil
}
// Enum values for Poolconditiontype // Enum values for Poolconditiontype
const ( const (
PoolconditiontypeBlue Poolconditiontype = "blue" PoolconditiontypeBlue Poolconditiontype = "blue"
@ -1629,6 +1550,85 @@ func (e *PublicreportNuisancedurationtype) Scan(value any) error {
return nil return nil
} }
// Enum values for PublicreportPermissionaccesstype
const (
PublicreportPermissionaccesstypeDenied PublicreportPermissionaccesstype = "denied"
PublicreportPermissionaccesstypeGranted PublicreportPermissionaccesstype = "granted"
PublicreportPermissionaccesstypeUnselected PublicreportPermissionaccesstype = "unselected"
PublicreportPermissionaccesstypeWithOwner PublicreportPermissionaccesstype = "with-owner"
)
func AllPublicreportPermissionaccesstype() []PublicreportPermissionaccesstype {
return []PublicreportPermissionaccesstype{
PublicreportPermissionaccesstypeDenied,
PublicreportPermissionaccesstypeGranted,
PublicreportPermissionaccesstypeUnselected,
PublicreportPermissionaccesstypeWithOwner,
}
}
type PublicreportPermissionaccesstype string
func (e PublicreportPermissionaccesstype) String() string {
return string(e)
}
func (e PublicreportPermissionaccesstype) Valid() bool {
switch e {
case PublicreportPermissionaccesstypeDenied,
PublicreportPermissionaccesstypeGranted,
PublicreportPermissionaccesstypeUnselected,
PublicreportPermissionaccesstypeWithOwner:
return true
default:
return false
}
}
// useful when testing in other packages
func (e PublicreportPermissionaccesstype) All() []PublicreportPermissionaccesstype {
return AllPublicreportPermissionaccesstype()
}
func (e PublicreportPermissionaccesstype) MarshalText() ([]byte, error) {
return []byte(e), nil
}
func (e *PublicreportPermissionaccesstype) UnmarshalText(text []byte) error {
return e.Scan(text)
}
func (e PublicreportPermissionaccesstype) MarshalBinary() ([]byte, error) {
return []byte(e), nil
}
func (e *PublicreportPermissionaccesstype) UnmarshalBinary(data []byte) error {
return e.Scan(data)
}
func (e PublicreportPermissionaccesstype) Value() (driver.Value, error) {
return string(e), nil
}
func (e *PublicreportPermissionaccesstype) Scan(value any) error {
switch x := value.(type) {
case string:
*e = PublicreportPermissionaccesstype(x)
case []byte:
*e = PublicreportPermissionaccesstype(x)
case nil:
return fmt.Errorf("cannot nil into PublicreportPermissionaccesstype")
default:
return fmt.Errorf("cannot scan type %T: %v", value, value)
}
if !e.Valid() {
return fmt.Errorf("invalid PublicreportPermissionaccesstype value: %s", *e)
}
return nil
}
// Enum values for PublicreportPoolsourceduration // Enum values for PublicreportPoolsourceduration
const ( const (
PublicreportPoolsourcedurationNone PublicreportPoolsourceduration = "none" PublicreportPoolsourcedurationNone PublicreportPoolsourceduration = "none"

View file

@ -0,0 +1,6 @@
-- +goose Up
ALTER TABLE communication
ADD COLUMN set_possible_issue TIMESTAMP WITHOUT TIME ZONE,
ADD COLUMN set_possible_issue_by INTEGER REFERENCES user_(id),
ADD COLUMN set_possible_resolved TIMESTAMP WITHOUT TIME ZONE,
ADD COLUMN set_possible_resolved_by INTEGER REFERENCES user_(id);

View file

@ -33,6 +33,7 @@ type Communication struct {
InvalidatedBy null.Val[int32] `db:"invalidated_by" ` InvalidatedBy null.Val[int32] `db:"invalidated_by" `
Opened null.Val[time.Time] `db:"opened" ` Opened null.Val[time.Time] `db:"opened" `
OpenedBy null.Val[int32] `db:"opened_by" ` OpenedBy null.Val[int32] `db:"opened_by" `
OrganizationID int32 `db:"organization_id" `
ResponseEmailLogID null.Val[int32] `db:"response_email_log_id" ` ResponseEmailLogID null.Val[int32] `db:"response_email_log_id" `
ResponseTextLogID null.Val[int32] `db:"response_text_log_id" ` ResponseTextLogID null.Val[int32] `db:"response_text_log_id" `
SetPending null.Val[time.Time] `db:"set_pending" ` SetPending null.Val[time.Time] `db:"set_pending" `
@ -40,6 +41,10 @@ type Communication struct {
SourceEmailLogID null.Val[int32] `db:"source_email_log_id" ` SourceEmailLogID null.Val[int32] `db:"source_email_log_id" `
SourceReportID null.Val[int32] `db:"source_report_id" ` SourceReportID null.Val[int32] `db:"source_report_id" `
SourceTextLogID null.Val[int32] `db:"source_text_log_id" ` SourceTextLogID null.Val[int32] `db:"source_text_log_id" `
SetPossibleIssue null.Val[time.Time] `db:"set_possible_issue" `
SetPossibleIssueBy null.Val[int32] `db:"set_possible_issue_by" `
SetPossibleResolved null.Val[time.Time] `db:"set_possible_resolved" `
SetPossibleResolvedBy null.Val[int32] `db:"set_possible_resolved_by" `
R communicationR `db:"-" ` R communicationR `db:"-" `
} }
@ -59,9 +64,12 @@ type communicationR struct {
ClosedByUser *User // communication.communication_closed_by_fkey ClosedByUser *User // communication.communication_closed_by_fkey
InvalidatedByUser *User // communication.communication_invalidated_by_fkey InvalidatedByUser *User // communication.communication_invalidated_by_fkey
OpenedByUser *User // communication.communication_opened_by_fkey OpenedByUser *User // communication.communication_opened_by_fkey
Organization *Organization // communication.communication_organization_id_fkey
ResponseEmailLogEmailLog *CommsEmailLog // communication.communication_response_email_log_id_fkey ResponseEmailLogEmailLog *CommsEmailLog // communication.communication_response_email_log_id_fkey
ResponseTextLogTextLog *CommsTextLog // communication.communication_response_text_log_id_fkey ResponseTextLogTextLog *CommsTextLog // communication.communication_response_text_log_id_fkey
SetPendingByUser *User // communication.communication_set_pending_by_fkey SetPendingByUser *User // communication.communication_set_pending_by_fkey
SetPossibleIssueByUser *User // communication.communication_set_possible_issue_by_fkey
SetPossibleResolvedByUser *User // communication.communication_set_possible_resolved_by_fkey
SourceEmailLogEmailLog *CommsEmailLog // communication.communication_source_email_log_id_fkey SourceEmailLogEmailLog *CommsEmailLog // communication.communication_source_email_log_id_fkey
SourceReportReport *PublicreportReport // communication.communication_source_report_id_fkey SourceReportReport *PublicreportReport // communication.communication_source_report_id_fkey
SourceTextLogTextLog *CommsTextLog // communication.communication_source_text_log_id_fkey SourceTextLogTextLog *CommsTextLog // communication.communication_source_text_log_id_fkey
@ -70,7 +78,7 @@ type communicationR struct {
func buildCommunicationColumns(alias string) communicationColumns { func buildCommunicationColumns(alias string) communicationColumns {
return communicationColumns{ return communicationColumns{
ColumnsExpr: expr.NewColumnsExpr( ColumnsExpr: expr.NewColumnsExpr(
"closed", "closed_by", "created", "id", "invalidated", "invalidated_by", "opened", "opened_by", "response_email_log_id", "response_text_log_id", "set_pending", "set_pending_by", "source_email_log_id", "source_report_id", "source_text_log_id", "closed", "closed_by", "created", "id", "invalidated", "invalidated_by", "opened", "opened_by", "organization_id", "response_email_log_id", "response_text_log_id", "set_pending", "set_pending_by", "source_email_log_id", "source_report_id", "source_text_log_id", "set_possible_issue", "set_possible_issue_by", "set_possible_resolved", "set_possible_resolved_by",
).WithParent("communication"), ).WithParent("communication"),
tableAlias: alias, tableAlias: alias,
Closed: psql.Quote(alias, "closed"), Closed: psql.Quote(alias, "closed"),
@ -81,6 +89,7 @@ func buildCommunicationColumns(alias string) communicationColumns {
InvalidatedBy: psql.Quote(alias, "invalidated_by"), InvalidatedBy: psql.Quote(alias, "invalidated_by"),
Opened: psql.Quote(alias, "opened"), Opened: psql.Quote(alias, "opened"),
OpenedBy: psql.Quote(alias, "opened_by"), OpenedBy: psql.Quote(alias, "opened_by"),
OrganizationID: psql.Quote(alias, "organization_id"),
ResponseEmailLogID: psql.Quote(alias, "response_email_log_id"), ResponseEmailLogID: psql.Quote(alias, "response_email_log_id"),
ResponseTextLogID: psql.Quote(alias, "response_text_log_id"), ResponseTextLogID: psql.Quote(alias, "response_text_log_id"),
SetPending: psql.Quote(alias, "set_pending"), SetPending: psql.Quote(alias, "set_pending"),
@ -88,6 +97,10 @@ func buildCommunicationColumns(alias string) communicationColumns {
SourceEmailLogID: psql.Quote(alias, "source_email_log_id"), SourceEmailLogID: psql.Quote(alias, "source_email_log_id"),
SourceReportID: psql.Quote(alias, "source_report_id"), SourceReportID: psql.Quote(alias, "source_report_id"),
SourceTextLogID: psql.Quote(alias, "source_text_log_id"), SourceTextLogID: psql.Quote(alias, "source_text_log_id"),
SetPossibleIssue: psql.Quote(alias, "set_possible_issue"),
SetPossibleIssueBy: psql.Quote(alias, "set_possible_issue_by"),
SetPossibleResolved: psql.Quote(alias, "set_possible_resolved"),
SetPossibleResolvedBy: psql.Quote(alias, "set_possible_resolved_by"),
} }
} }
@ -102,6 +115,7 @@ type communicationColumns struct {
InvalidatedBy psql.Expression InvalidatedBy psql.Expression
Opened psql.Expression Opened psql.Expression
OpenedBy psql.Expression OpenedBy psql.Expression
OrganizationID psql.Expression
ResponseEmailLogID psql.Expression ResponseEmailLogID psql.Expression
ResponseTextLogID psql.Expression ResponseTextLogID psql.Expression
SetPending psql.Expression SetPending psql.Expression
@ -109,6 +123,10 @@ type communicationColumns struct {
SourceEmailLogID psql.Expression SourceEmailLogID psql.Expression
SourceReportID psql.Expression SourceReportID psql.Expression
SourceTextLogID psql.Expression SourceTextLogID psql.Expression
SetPossibleIssue psql.Expression
SetPossibleIssueBy psql.Expression
SetPossibleResolved psql.Expression
SetPossibleResolvedBy psql.Expression
} }
func (c communicationColumns) Alias() string { func (c communicationColumns) Alias() string {
@ -131,6 +149,7 @@ type CommunicationSetter struct {
InvalidatedBy omitnull.Val[int32] `db:"invalidated_by" ` InvalidatedBy omitnull.Val[int32] `db:"invalidated_by" `
Opened omitnull.Val[time.Time] `db:"opened" ` Opened omitnull.Val[time.Time] `db:"opened" `
OpenedBy omitnull.Val[int32] `db:"opened_by" ` OpenedBy omitnull.Val[int32] `db:"opened_by" `
OrganizationID omit.Val[int32] `db:"organization_id" `
ResponseEmailLogID omitnull.Val[int32] `db:"response_email_log_id" ` ResponseEmailLogID omitnull.Val[int32] `db:"response_email_log_id" `
ResponseTextLogID omitnull.Val[int32] `db:"response_text_log_id" ` ResponseTextLogID omitnull.Val[int32] `db:"response_text_log_id" `
SetPending omitnull.Val[time.Time] `db:"set_pending" ` SetPending omitnull.Val[time.Time] `db:"set_pending" `
@ -138,10 +157,14 @@ type CommunicationSetter struct {
SourceEmailLogID omitnull.Val[int32] `db:"source_email_log_id" ` SourceEmailLogID omitnull.Val[int32] `db:"source_email_log_id" `
SourceReportID omitnull.Val[int32] `db:"source_report_id" ` SourceReportID omitnull.Val[int32] `db:"source_report_id" `
SourceTextLogID omitnull.Val[int32] `db:"source_text_log_id" ` SourceTextLogID omitnull.Val[int32] `db:"source_text_log_id" `
SetPossibleIssue omitnull.Val[time.Time] `db:"set_possible_issue" `
SetPossibleIssueBy omitnull.Val[int32] `db:"set_possible_issue_by" `
SetPossibleResolved omitnull.Val[time.Time] `db:"set_possible_resolved" `
SetPossibleResolvedBy omitnull.Val[int32] `db:"set_possible_resolved_by" `
} }
func (s CommunicationSetter) SetColumns() []string { func (s CommunicationSetter) SetColumns() []string {
vals := make([]string, 0, 15) vals := make([]string, 0, 20)
if !s.Closed.IsUnset() { if !s.Closed.IsUnset() {
vals = append(vals, "closed") vals = append(vals, "closed")
} }
@ -166,6 +189,9 @@ func (s CommunicationSetter) SetColumns() []string {
if !s.OpenedBy.IsUnset() { if !s.OpenedBy.IsUnset() {
vals = append(vals, "opened_by") vals = append(vals, "opened_by")
} }
if s.OrganizationID.IsValue() {
vals = append(vals, "organization_id")
}
if !s.ResponseEmailLogID.IsUnset() { if !s.ResponseEmailLogID.IsUnset() {
vals = append(vals, "response_email_log_id") vals = append(vals, "response_email_log_id")
} }
@ -187,6 +213,18 @@ func (s CommunicationSetter) SetColumns() []string {
if !s.SourceTextLogID.IsUnset() { if !s.SourceTextLogID.IsUnset() {
vals = append(vals, "source_text_log_id") vals = append(vals, "source_text_log_id")
} }
if !s.SetPossibleIssue.IsUnset() {
vals = append(vals, "set_possible_issue")
}
if !s.SetPossibleIssueBy.IsUnset() {
vals = append(vals, "set_possible_issue_by")
}
if !s.SetPossibleResolved.IsUnset() {
vals = append(vals, "set_possible_resolved")
}
if !s.SetPossibleResolvedBy.IsUnset() {
vals = append(vals, "set_possible_resolved_by")
}
return vals return vals
} }
@ -215,6 +253,9 @@ func (s CommunicationSetter) Overwrite(t *Communication) {
if !s.OpenedBy.IsUnset() { if !s.OpenedBy.IsUnset() {
t.OpenedBy = s.OpenedBy.MustGetNull() t.OpenedBy = s.OpenedBy.MustGetNull()
} }
if s.OrganizationID.IsValue() {
t.OrganizationID = s.OrganizationID.MustGet()
}
if !s.ResponseEmailLogID.IsUnset() { if !s.ResponseEmailLogID.IsUnset() {
t.ResponseEmailLogID = s.ResponseEmailLogID.MustGetNull() t.ResponseEmailLogID = s.ResponseEmailLogID.MustGetNull()
} }
@ -236,6 +277,18 @@ func (s CommunicationSetter) Overwrite(t *Communication) {
if !s.SourceTextLogID.IsUnset() { if !s.SourceTextLogID.IsUnset() {
t.SourceTextLogID = s.SourceTextLogID.MustGetNull() t.SourceTextLogID = s.SourceTextLogID.MustGetNull()
} }
if !s.SetPossibleIssue.IsUnset() {
t.SetPossibleIssue = s.SetPossibleIssue.MustGetNull()
}
if !s.SetPossibleIssueBy.IsUnset() {
t.SetPossibleIssueBy = s.SetPossibleIssueBy.MustGetNull()
}
if !s.SetPossibleResolved.IsUnset() {
t.SetPossibleResolved = s.SetPossibleResolved.MustGetNull()
}
if !s.SetPossibleResolvedBy.IsUnset() {
t.SetPossibleResolvedBy = s.SetPossibleResolvedBy.MustGetNull()
}
} }
func (s *CommunicationSetter) Apply(q *dialect.InsertQuery) { func (s *CommunicationSetter) Apply(q *dialect.InsertQuery) {
@ -244,7 +297,7 @@ func (s *CommunicationSetter) Apply(q *dialect.InsertQuery) {
}) })
q.AppendValues(bob.ExpressionFunc(func(ctx context.Context, w io.StringWriter, d bob.Dialect, start int) ([]any, error) { q.AppendValues(bob.ExpressionFunc(func(ctx context.Context, w io.StringWriter, d bob.Dialect, start int) ([]any, error) {
vals := make([]bob.Expression, 15) vals := make([]bob.Expression, 20)
if !s.Closed.IsUnset() { if !s.Closed.IsUnset() {
vals[0] = psql.Arg(s.Closed.MustGetNull()) vals[0] = psql.Arg(s.Closed.MustGetNull())
} else { } else {
@ -293,48 +346,78 @@ func (s *CommunicationSetter) Apply(q *dialect.InsertQuery) {
vals[7] = psql.Raw("DEFAULT") vals[7] = psql.Raw("DEFAULT")
} }
if !s.ResponseEmailLogID.IsUnset() { if s.OrganizationID.IsValue() {
vals[8] = psql.Arg(s.ResponseEmailLogID.MustGetNull()) vals[8] = psql.Arg(s.OrganizationID.MustGet())
} else { } else {
vals[8] = psql.Raw("DEFAULT") vals[8] = psql.Raw("DEFAULT")
} }
if !s.ResponseTextLogID.IsUnset() { if !s.ResponseEmailLogID.IsUnset() {
vals[9] = psql.Arg(s.ResponseTextLogID.MustGetNull()) vals[9] = psql.Arg(s.ResponseEmailLogID.MustGetNull())
} else { } else {
vals[9] = psql.Raw("DEFAULT") vals[9] = psql.Raw("DEFAULT")
} }
if !s.SetPending.IsUnset() { if !s.ResponseTextLogID.IsUnset() {
vals[10] = psql.Arg(s.SetPending.MustGetNull()) vals[10] = psql.Arg(s.ResponseTextLogID.MustGetNull())
} else { } else {
vals[10] = psql.Raw("DEFAULT") vals[10] = psql.Raw("DEFAULT")
} }
if !s.SetPendingBy.IsUnset() { if !s.SetPending.IsUnset() {
vals[11] = psql.Arg(s.SetPendingBy.MustGetNull()) vals[11] = psql.Arg(s.SetPending.MustGetNull())
} else { } else {
vals[11] = psql.Raw("DEFAULT") vals[11] = psql.Raw("DEFAULT")
} }
if !s.SourceEmailLogID.IsUnset() { if !s.SetPendingBy.IsUnset() {
vals[12] = psql.Arg(s.SourceEmailLogID.MustGetNull()) vals[12] = psql.Arg(s.SetPendingBy.MustGetNull())
} else { } else {
vals[12] = psql.Raw("DEFAULT") vals[12] = psql.Raw("DEFAULT")
} }
if !s.SourceReportID.IsUnset() { if !s.SourceEmailLogID.IsUnset() {
vals[13] = psql.Arg(s.SourceReportID.MustGetNull()) vals[13] = psql.Arg(s.SourceEmailLogID.MustGetNull())
} else { } else {
vals[13] = psql.Raw("DEFAULT") vals[13] = psql.Raw("DEFAULT")
} }
if !s.SourceTextLogID.IsUnset() { if !s.SourceReportID.IsUnset() {
vals[14] = psql.Arg(s.SourceTextLogID.MustGetNull()) vals[14] = psql.Arg(s.SourceReportID.MustGetNull())
} else { } else {
vals[14] = psql.Raw("DEFAULT") vals[14] = psql.Raw("DEFAULT")
} }
if !s.SourceTextLogID.IsUnset() {
vals[15] = psql.Arg(s.SourceTextLogID.MustGetNull())
} else {
vals[15] = psql.Raw("DEFAULT")
}
if !s.SetPossibleIssue.IsUnset() {
vals[16] = psql.Arg(s.SetPossibleIssue.MustGetNull())
} else {
vals[16] = psql.Raw("DEFAULT")
}
if !s.SetPossibleIssueBy.IsUnset() {
vals[17] = psql.Arg(s.SetPossibleIssueBy.MustGetNull())
} else {
vals[17] = psql.Raw("DEFAULT")
}
if !s.SetPossibleResolved.IsUnset() {
vals[18] = psql.Arg(s.SetPossibleResolved.MustGetNull())
} else {
vals[18] = psql.Raw("DEFAULT")
}
if !s.SetPossibleResolvedBy.IsUnset() {
vals[19] = psql.Arg(s.SetPossibleResolvedBy.MustGetNull())
} else {
vals[19] = psql.Raw("DEFAULT")
}
return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "") return bob.ExpressSlice(ctx, w, d, start, vals, "", ", ", "")
})) }))
} }
@ -344,7 +427,7 @@ func (s CommunicationSetter) UpdateMod() bob.Mod[*dialect.UpdateQuery] {
} }
func (s CommunicationSetter) Expressions(prefix ...string) []bob.Expression { func (s CommunicationSetter) Expressions(prefix ...string) []bob.Expression {
exprs := make([]bob.Expression, 0, 15) exprs := make([]bob.Expression, 0, 20)
if !s.Closed.IsUnset() { if !s.Closed.IsUnset() {
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
@ -402,6 +485,13 @@ func (s CommunicationSetter) Expressions(prefix ...string) []bob.Expression {
}}) }})
} }
if s.OrganizationID.IsValue() {
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
psql.Quote(append(prefix, "organization_id")...),
psql.Arg(s.OrganizationID),
}})
}
if !s.ResponseEmailLogID.IsUnset() { if !s.ResponseEmailLogID.IsUnset() {
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{ exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
psql.Quote(append(prefix, "response_email_log_id")...), psql.Quote(append(prefix, "response_email_log_id")...),
@ -451,6 +541,34 @@ func (s CommunicationSetter) Expressions(prefix ...string) []bob.Expression {
}}) }})
} }
if !s.SetPossibleIssue.IsUnset() {
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
psql.Quote(append(prefix, "set_possible_issue")...),
psql.Arg(s.SetPossibleIssue),
}})
}
if !s.SetPossibleIssueBy.IsUnset() {
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
psql.Quote(append(prefix, "set_possible_issue_by")...),
psql.Arg(s.SetPossibleIssueBy),
}})
}
if !s.SetPossibleResolved.IsUnset() {
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
psql.Quote(append(prefix, "set_possible_resolved")...),
psql.Arg(s.SetPossibleResolved),
}})
}
if !s.SetPossibleResolvedBy.IsUnset() {
exprs = append(exprs, expr.Join{Sep: " = ", Exprs: []bob.Expression{
psql.Quote(append(prefix, "set_possible_resolved_by")...),
psql.Arg(s.SetPossibleResolvedBy),
}})
}
return exprs return exprs
} }
@ -749,6 +867,30 @@ func (os CommunicationSlice) OpenedByUser(mods ...bob.Mod[*dialect.SelectQuery])
)...) )...)
} }
// Organization starts a query for related objects on organization
func (o *Communication) Organization(mods ...bob.Mod[*dialect.SelectQuery]) OrganizationsQuery {
return Organizations.Query(append(mods,
sm.Where(Organizations.Columns.ID.EQ(psql.Arg(o.OrganizationID))),
)...)
}
func (os CommunicationSlice) Organization(mods ...bob.Mod[*dialect.SelectQuery]) OrganizationsQuery {
pkOrganizationID := make(pgtypes.Array[int32], 0, len(os))
for _, o := range os {
if o == nil {
continue
}
pkOrganizationID = append(pkOrganizationID, o.OrganizationID)
}
PKArgExpr := psql.Select(sm.Columns(
psql.F("unnest", psql.Cast(psql.Arg(pkOrganizationID), "integer[]")),
))
return Organizations.Query(append(mods,
sm.Where(psql.Group(Organizations.Columns.ID).OP("IN", PKArgExpr)),
)...)
}
// ResponseEmailLogEmailLog starts a query for related objects on comms.email_log // ResponseEmailLogEmailLog starts a query for related objects on comms.email_log
func (o *Communication) ResponseEmailLogEmailLog(mods ...bob.Mod[*dialect.SelectQuery]) CommsEmailLogsQuery { func (o *Communication) ResponseEmailLogEmailLog(mods ...bob.Mod[*dialect.SelectQuery]) CommsEmailLogsQuery {
return CommsEmailLogs.Query(append(mods, return CommsEmailLogs.Query(append(mods,
@ -821,6 +963,54 @@ func (os CommunicationSlice) SetPendingByUser(mods ...bob.Mod[*dialect.SelectQue
)...) )...)
} }
// SetPossibleIssueByUser starts a query for related objects on user_
func (o *Communication) SetPossibleIssueByUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery {
return Users.Query(append(mods,
sm.Where(Users.Columns.ID.EQ(psql.Arg(o.SetPossibleIssueBy))),
)...)
}
func (os CommunicationSlice) SetPossibleIssueByUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery {
pkSetPossibleIssueBy := make(pgtypes.Array[null.Val[int32]], 0, len(os))
for _, o := range os {
if o == nil {
continue
}
pkSetPossibleIssueBy = append(pkSetPossibleIssueBy, o.SetPossibleIssueBy)
}
PKArgExpr := psql.Select(sm.Columns(
psql.F("unnest", psql.Cast(psql.Arg(pkSetPossibleIssueBy), "integer[]")),
))
return Users.Query(append(mods,
sm.Where(psql.Group(Users.Columns.ID).OP("IN", PKArgExpr)),
)...)
}
// SetPossibleResolvedByUser starts a query for related objects on user_
func (o *Communication) SetPossibleResolvedByUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery {
return Users.Query(append(mods,
sm.Where(Users.Columns.ID.EQ(psql.Arg(o.SetPossibleResolvedBy))),
)...)
}
func (os CommunicationSlice) SetPossibleResolvedByUser(mods ...bob.Mod[*dialect.SelectQuery]) UsersQuery {
pkSetPossibleResolvedBy := make(pgtypes.Array[null.Val[int32]], 0, len(os))
for _, o := range os {
if o == nil {
continue
}
pkSetPossibleResolvedBy = append(pkSetPossibleResolvedBy, o.SetPossibleResolvedBy)
}
PKArgExpr := psql.Select(sm.Columns(
psql.F("unnest", psql.Cast(psql.Arg(pkSetPossibleResolvedBy), "integer[]")),
))
return Users.Query(append(mods,
sm.Where(psql.Group(Users.Columns.ID).OP("IN", PKArgExpr)),
)...)
}
// SourceEmailLogEmailLog starts a query for related objects on comms.email_log // SourceEmailLogEmailLog starts a query for related objects on comms.email_log
func (o *Communication) SourceEmailLogEmailLog(mods ...bob.Mod[*dialect.SelectQuery]) CommsEmailLogsQuery { func (o *Communication) SourceEmailLogEmailLog(mods ...bob.Mod[*dialect.SelectQuery]) CommsEmailLogsQuery {
return CommsEmailLogs.Query(append(mods, return CommsEmailLogs.Query(append(mods,
@ -1037,6 +1227,54 @@ func (communication0 *Communication) AttachOpenedByUser(ctx context.Context, exe
return nil return nil
} }
func attachCommunicationOrganization0(ctx context.Context, exec bob.Executor, count int, communication0 *Communication, organization1 *Organization) (*Communication, error) {
setter := &CommunicationSetter{
OrganizationID: omit.From(organization1.ID),
}
err := communication0.Update(ctx, exec, setter)
if err != nil {
return nil, fmt.Errorf("attachCommunicationOrganization0: %w", err)
}
return communication0, nil
}
func (communication0 *Communication) InsertOrganization(ctx context.Context, exec bob.Executor, related *OrganizationSetter) error {
var err error
organization1, err := Organizations.Insert(related).One(ctx, exec)
if err != nil {
return fmt.Errorf("inserting related objects: %w", err)
}
_, err = attachCommunicationOrganization0(ctx, exec, 1, communication0, organization1)
if err != nil {
return err
}
communication0.R.Organization = organization1
organization1.R.Communications = append(organization1.R.Communications, communication0)
return nil
}
func (communication0 *Communication) AttachOrganization(ctx context.Context, exec bob.Executor, organization1 *Organization) error {
var err error
_, err = attachCommunicationOrganization0(ctx, exec, 1, communication0, organization1)
if err != nil {
return err
}
communication0.R.Organization = organization1
organization1.R.Communications = append(organization1.R.Communications, communication0)
return nil
}
func attachCommunicationResponseEmailLogEmailLog0(ctx context.Context, exec bob.Executor, count int, communication0 *Communication, commsEmailLog1 *CommsEmailLog) (*Communication, error) { func attachCommunicationResponseEmailLogEmailLog0(ctx context.Context, exec bob.Executor, count int, communication0 *Communication, commsEmailLog1 *CommsEmailLog) (*Communication, error) {
setter := &CommunicationSetter{ setter := &CommunicationSetter{
ResponseEmailLogID: omitnull.From(commsEmailLog1.ID), ResponseEmailLogID: omitnull.From(commsEmailLog1.ID),
@ -1181,6 +1419,102 @@ func (communication0 *Communication) AttachSetPendingByUser(ctx context.Context,
return nil return nil
} }
func attachCommunicationSetPossibleIssueByUser0(ctx context.Context, exec bob.Executor, count int, communication0 *Communication, user1 *User) (*Communication, error) {
setter := &CommunicationSetter{
SetPossibleIssueBy: omitnull.From(user1.ID),
}
err := communication0.Update(ctx, exec, setter)
if err != nil {
return nil, fmt.Errorf("attachCommunicationSetPossibleIssueByUser0: %w", err)
}
return communication0, nil
}
func (communication0 *Communication) InsertSetPossibleIssueByUser(ctx context.Context, exec bob.Executor, related *UserSetter) error {
var err error
user1, err := Users.Insert(related).One(ctx, exec)
if err != nil {
return fmt.Errorf("inserting related objects: %w", err)
}
_, err = attachCommunicationSetPossibleIssueByUser0(ctx, exec, 1, communication0, user1)
if err != nil {
return err
}
communication0.R.SetPossibleIssueByUser = user1
user1.R.SetPossibleIssueByCommunications = append(user1.R.SetPossibleIssueByCommunications, communication0)
return nil
}
func (communication0 *Communication) AttachSetPossibleIssueByUser(ctx context.Context, exec bob.Executor, user1 *User) error {
var err error
_, err = attachCommunicationSetPossibleIssueByUser0(ctx, exec, 1, communication0, user1)
if err != nil {
return err
}
communication0.R.SetPossibleIssueByUser = user1
user1.R.SetPossibleIssueByCommunications = append(user1.R.SetPossibleIssueByCommunications, communication0)
return nil
}
func attachCommunicationSetPossibleResolvedByUser0(ctx context.Context, exec bob.Executor, count int, communication0 *Communication, user1 *User) (*Communication, error) {
setter := &CommunicationSetter{
SetPossibleResolvedBy: omitnull.From(user1.ID),
}
err := communication0.Update(ctx, exec, setter)
if err != nil {
return nil, fmt.Errorf("attachCommunicationSetPossibleResolvedByUser0: %w", err)
}
return communication0, nil
}
func (communication0 *Communication) InsertSetPossibleResolvedByUser(ctx context.Context, exec bob.Executor, related *UserSetter) error {
var err error
user1, err := Users.Insert(related).One(ctx, exec)
if err != nil {
return fmt.Errorf("inserting related objects: %w", err)
}
_, err = attachCommunicationSetPossibleResolvedByUser0(ctx, exec, 1, communication0, user1)
if err != nil {
return err
}
communication0.R.SetPossibleResolvedByUser = user1
user1.R.SetPossibleResolvedByCommunications = append(user1.R.SetPossibleResolvedByCommunications, communication0)
return nil
}
func (communication0 *Communication) AttachSetPossibleResolvedByUser(ctx context.Context, exec bob.Executor, user1 *User) error {
var err error
_, err = attachCommunicationSetPossibleResolvedByUser0(ctx, exec, 1, communication0, user1)
if err != nil {
return err
}
communication0.R.SetPossibleResolvedByUser = user1
user1.R.SetPossibleResolvedByCommunications = append(user1.R.SetPossibleResolvedByCommunications, communication0)
return nil
}
func attachCommunicationSourceEmailLogEmailLog0(ctx context.Context, exec bob.Executor, count int, communication0 *Communication, commsEmailLog1 *CommsEmailLog) (*Communication, error) { func attachCommunicationSourceEmailLogEmailLog0(ctx context.Context, exec bob.Executor, count int, communication0 *Communication, commsEmailLog1 *CommsEmailLog) (*Communication, error) {
setter := &CommunicationSetter{ setter := &CommunicationSetter{
SourceEmailLogID: omitnull.From(commsEmailLog1.ID), SourceEmailLogID: omitnull.From(commsEmailLog1.ID),
@ -1334,6 +1668,7 @@ type communicationWhere[Q psql.Filterable] struct {
InvalidatedBy psql.WhereNullMod[Q, int32] InvalidatedBy psql.WhereNullMod[Q, int32]
Opened psql.WhereNullMod[Q, time.Time] Opened psql.WhereNullMod[Q, time.Time]
OpenedBy psql.WhereNullMod[Q, int32] OpenedBy psql.WhereNullMod[Q, int32]
OrganizationID psql.WhereMod[Q, int32]
ResponseEmailLogID psql.WhereNullMod[Q, int32] ResponseEmailLogID psql.WhereNullMod[Q, int32]
ResponseTextLogID psql.WhereNullMod[Q, int32] ResponseTextLogID psql.WhereNullMod[Q, int32]
SetPending psql.WhereNullMod[Q, time.Time] SetPending psql.WhereNullMod[Q, time.Time]
@ -1341,6 +1676,10 @@ type communicationWhere[Q psql.Filterable] struct {
SourceEmailLogID psql.WhereNullMod[Q, int32] SourceEmailLogID psql.WhereNullMod[Q, int32]
SourceReportID psql.WhereNullMod[Q, int32] SourceReportID psql.WhereNullMod[Q, int32]
SourceTextLogID psql.WhereNullMod[Q, int32] SourceTextLogID psql.WhereNullMod[Q, int32]
SetPossibleIssue psql.WhereNullMod[Q, time.Time]
SetPossibleIssueBy psql.WhereNullMod[Q, int32]
SetPossibleResolved psql.WhereNullMod[Q, time.Time]
SetPossibleResolvedBy psql.WhereNullMod[Q, int32]
} }
func (communicationWhere[Q]) AliasedAs(alias string) communicationWhere[Q] { func (communicationWhere[Q]) AliasedAs(alias string) communicationWhere[Q] {
@ -1357,6 +1696,7 @@ func buildCommunicationWhere[Q psql.Filterable](cols communicationColumns) commu
InvalidatedBy: psql.WhereNull[Q, int32](cols.InvalidatedBy), InvalidatedBy: psql.WhereNull[Q, int32](cols.InvalidatedBy),
Opened: psql.WhereNull[Q, time.Time](cols.Opened), Opened: psql.WhereNull[Q, time.Time](cols.Opened),
OpenedBy: psql.WhereNull[Q, int32](cols.OpenedBy), OpenedBy: psql.WhereNull[Q, int32](cols.OpenedBy),
OrganizationID: psql.Where[Q, int32](cols.OrganizationID),
ResponseEmailLogID: psql.WhereNull[Q, int32](cols.ResponseEmailLogID), ResponseEmailLogID: psql.WhereNull[Q, int32](cols.ResponseEmailLogID),
ResponseTextLogID: psql.WhereNull[Q, int32](cols.ResponseTextLogID), ResponseTextLogID: psql.WhereNull[Q, int32](cols.ResponseTextLogID),
SetPending: psql.WhereNull[Q, time.Time](cols.SetPending), SetPending: psql.WhereNull[Q, time.Time](cols.SetPending),
@ -1364,6 +1704,10 @@ func buildCommunicationWhere[Q psql.Filterable](cols communicationColumns) commu
SourceEmailLogID: psql.WhereNull[Q, int32](cols.SourceEmailLogID), SourceEmailLogID: psql.WhereNull[Q, int32](cols.SourceEmailLogID),
SourceReportID: psql.WhereNull[Q, int32](cols.SourceReportID), SourceReportID: psql.WhereNull[Q, int32](cols.SourceReportID),
SourceTextLogID: psql.WhereNull[Q, int32](cols.SourceTextLogID), SourceTextLogID: psql.WhereNull[Q, int32](cols.SourceTextLogID),
SetPossibleIssue: psql.WhereNull[Q, time.Time](cols.SetPossibleIssue),
SetPossibleIssueBy: psql.WhereNull[Q, int32](cols.SetPossibleIssueBy),
SetPossibleResolved: psql.WhereNull[Q, time.Time](cols.SetPossibleResolved),
SetPossibleResolvedBy: psql.WhereNull[Q, int32](cols.SetPossibleResolvedBy),
} }
} }
@ -1409,6 +1753,18 @@ func (o *Communication) Preload(name string, retrieved any) error {
rel.R.OpenedByCommunications = CommunicationSlice{o} rel.R.OpenedByCommunications = CommunicationSlice{o}
} }
return nil return nil
case "Organization":
rel, ok := retrieved.(*Organization)
if !ok {
return fmt.Errorf("communication cannot load %T as %q", retrieved, name)
}
o.R.Organization = rel
if rel != nil {
rel.R.Communications = CommunicationSlice{o}
}
return nil
case "ResponseEmailLogEmailLog": case "ResponseEmailLogEmailLog":
rel, ok := retrieved.(*CommsEmailLog) rel, ok := retrieved.(*CommsEmailLog)
if !ok { if !ok {
@ -1445,6 +1801,30 @@ func (o *Communication) Preload(name string, retrieved any) error {
rel.R.SetPendingByCommunications = CommunicationSlice{o} rel.R.SetPendingByCommunications = CommunicationSlice{o}
} }
return nil return nil
case "SetPossibleIssueByUser":
rel, ok := retrieved.(*User)
if !ok {
return fmt.Errorf("communication cannot load %T as %q", retrieved, name)
}
o.R.SetPossibleIssueByUser = rel
if rel != nil {
rel.R.SetPossibleIssueByCommunications = CommunicationSlice{o}
}
return nil
case "SetPossibleResolvedByUser":
rel, ok := retrieved.(*User)
if !ok {
return fmt.Errorf("communication cannot load %T as %q", retrieved, name)
}
o.R.SetPossibleResolvedByUser = rel
if rel != nil {
rel.R.SetPossibleResolvedByCommunications = CommunicationSlice{o}
}
return nil
case "SourceEmailLogEmailLog": case "SourceEmailLogEmailLog":
rel, ok := retrieved.(*CommsEmailLog) rel, ok := retrieved.(*CommsEmailLog)
if !ok { if !ok {
@ -1490,9 +1870,12 @@ type communicationPreloader struct {
ClosedByUser func(...psql.PreloadOption) psql.Preloader ClosedByUser func(...psql.PreloadOption) psql.Preloader
InvalidatedByUser func(...psql.PreloadOption) psql.Preloader InvalidatedByUser func(...psql.PreloadOption) psql.Preloader
OpenedByUser func(...psql.PreloadOption) psql.Preloader OpenedByUser func(...psql.PreloadOption) psql.Preloader
Organization func(...psql.PreloadOption) psql.Preloader
ResponseEmailLogEmailLog func(...psql.PreloadOption) psql.Preloader ResponseEmailLogEmailLog func(...psql.PreloadOption) psql.Preloader
ResponseTextLogTextLog func(...psql.PreloadOption) psql.Preloader ResponseTextLogTextLog func(...psql.PreloadOption) psql.Preloader
SetPendingByUser func(...psql.PreloadOption) psql.Preloader SetPendingByUser func(...psql.PreloadOption) psql.Preloader
SetPossibleIssueByUser func(...psql.PreloadOption) psql.Preloader
SetPossibleResolvedByUser func(...psql.PreloadOption) psql.Preloader
SourceEmailLogEmailLog func(...psql.PreloadOption) psql.Preloader SourceEmailLogEmailLog func(...psql.PreloadOption) psql.Preloader
SourceReportReport func(...psql.PreloadOption) psql.Preloader SourceReportReport func(...psql.PreloadOption) psql.Preloader
SourceTextLogTextLog func(...psql.PreloadOption) psql.Preloader SourceTextLogTextLog func(...psql.PreloadOption) psql.Preloader
@ -1539,6 +1922,19 @@ func buildCommunicationPreloader() communicationPreloader {
}, },
}, Users.Columns.Names(), opts...) }, Users.Columns.Names(), opts...)
}, },
Organization: func(opts ...psql.PreloadOption) psql.Preloader {
return psql.Preload[*Organization, OrganizationSlice](psql.PreloadRel{
Name: "Organization",
Sides: []psql.PreloadSide{
{
From: Communications,
To: Organizations,
FromColumns: []string{"organization_id"},
ToColumns: []string{"id"},
},
},
}, Organizations.Columns.Names(), opts...)
},
ResponseEmailLogEmailLog: func(opts ...psql.PreloadOption) psql.Preloader { ResponseEmailLogEmailLog: func(opts ...psql.PreloadOption) psql.Preloader {
return psql.Preload[*CommsEmailLog, CommsEmailLogSlice](psql.PreloadRel{ return psql.Preload[*CommsEmailLog, CommsEmailLogSlice](psql.PreloadRel{
Name: "ResponseEmailLogEmailLog", Name: "ResponseEmailLogEmailLog",
@ -1578,6 +1974,32 @@ func buildCommunicationPreloader() communicationPreloader {
}, },
}, Users.Columns.Names(), opts...) }, Users.Columns.Names(), opts...)
}, },
SetPossibleIssueByUser: func(opts ...psql.PreloadOption) psql.Preloader {
return psql.Preload[*User, UserSlice](psql.PreloadRel{
Name: "SetPossibleIssueByUser",
Sides: []psql.PreloadSide{
{
From: Communications,
To: Users,
FromColumns: []string{"set_possible_issue_by"},
ToColumns: []string{"id"},
},
},
}, Users.Columns.Names(), opts...)
},
SetPossibleResolvedByUser: func(opts ...psql.PreloadOption) psql.Preloader {
return psql.Preload[*User, UserSlice](psql.PreloadRel{
Name: "SetPossibleResolvedByUser",
Sides: []psql.PreloadSide{
{
From: Communications,
To: Users,
FromColumns: []string{"set_possible_resolved_by"},
ToColumns: []string{"id"},
},
},
}, Users.Columns.Names(), opts...)
},
SourceEmailLogEmailLog: func(opts ...psql.PreloadOption) psql.Preloader { SourceEmailLogEmailLog: func(opts ...psql.PreloadOption) psql.Preloader {
return psql.Preload[*CommsEmailLog, CommsEmailLogSlice](psql.PreloadRel{ return psql.Preload[*CommsEmailLog, CommsEmailLogSlice](psql.PreloadRel{
Name: "SourceEmailLogEmailLog", Name: "SourceEmailLogEmailLog",
@ -1624,9 +2046,12 @@ type communicationThenLoader[Q orm.Loadable] struct {
ClosedByUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] ClosedByUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
InvalidatedByUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] InvalidatedByUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
OpenedByUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] OpenedByUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
Organization func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
ResponseEmailLogEmailLog func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] ResponseEmailLogEmailLog func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
ResponseTextLogTextLog func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] ResponseTextLogTextLog func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
SetPendingByUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] SetPendingByUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
SetPossibleIssueByUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
SetPossibleResolvedByUser func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
SourceEmailLogEmailLog func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] SourceEmailLogEmailLog func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
SourceReportReport func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] SourceReportReport func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
SourceTextLogTextLog func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] SourceTextLogTextLog func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
@ -1642,6 +2067,9 @@ func buildCommunicationThenLoader[Q orm.Loadable]() communicationThenLoader[Q] {
type OpenedByUserLoadInterface interface { type OpenedByUserLoadInterface interface {
LoadOpenedByUser(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error LoadOpenedByUser(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
} }
type OrganizationLoadInterface interface {
LoadOrganization(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
}
type ResponseEmailLogEmailLogLoadInterface interface { type ResponseEmailLogEmailLogLoadInterface interface {
LoadResponseEmailLogEmailLog(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error LoadResponseEmailLogEmailLog(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
} }
@ -1651,6 +2079,12 @@ func buildCommunicationThenLoader[Q orm.Loadable]() communicationThenLoader[Q] {
type SetPendingByUserLoadInterface interface { type SetPendingByUserLoadInterface interface {
LoadSetPendingByUser(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error LoadSetPendingByUser(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
} }
type SetPossibleIssueByUserLoadInterface interface {
LoadSetPossibleIssueByUser(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
}
type SetPossibleResolvedByUserLoadInterface interface {
LoadSetPossibleResolvedByUser(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
}
type SourceEmailLogEmailLogLoadInterface interface { type SourceEmailLogEmailLogLoadInterface interface {
LoadSourceEmailLogEmailLog(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error LoadSourceEmailLogEmailLog(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
} }
@ -1680,6 +2114,12 @@ func buildCommunicationThenLoader[Q orm.Loadable]() communicationThenLoader[Q] {
return retrieved.LoadOpenedByUser(ctx, exec, mods...) return retrieved.LoadOpenedByUser(ctx, exec, mods...)
}, },
), ),
Organization: thenLoadBuilder[Q](
"Organization",
func(ctx context.Context, exec bob.Executor, retrieved OrganizationLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
return retrieved.LoadOrganization(ctx, exec, mods...)
},
),
ResponseEmailLogEmailLog: thenLoadBuilder[Q]( ResponseEmailLogEmailLog: thenLoadBuilder[Q](
"ResponseEmailLogEmailLog", "ResponseEmailLogEmailLog",
func(ctx context.Context, exec bob.Executor, retrieved ResponseEmailLogEmailLogLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { func(ctx context.Context, exec bob.Executor, retrieved ResponseEmailLogEmailLogLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
@ -1698,6 +2138,18 @@ func buildCommunicationThenLoader[Q orm.Loadable]() communicationThenLoader[Q] {
return retrieved.LoadSetPendingByUser(ctx, exec, mods...) return retrieved.LoadSetPendingByUser(ctx, exec, mods...)
}, },
), ),
SetPossibleIssueByUser: thenLoadBuilder[Q](
"SetPossibleIssueByUser",
func(ctx context.Context, exec bob.Executor, retrieved SetPossibleIssueByUserLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
return retrieved.LoadSetPossibleIssueByUser(ctx, exec, mods...)
},
),
SetPossibleResolvedByUser: thenLoadBuilder[Q](
"SetPossibleResolvedByUser",
func(ctx context.Context, exec bob.Executor, retrieved SetPossibleResolvedByUserLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
return retrieved.LoadSetPossibleResolvedByUser(ctx, exec, mods...)
},
),
SourceEmailLogEmailLog: thenLoadBuilder[Q]( SourceEmailLogEmailLog: thenLoadBuilder[Q](
"SourceEmailLogEmailLog", "SourceEmailLogEmailLog",
func(ctx context.Context, exec bob.Executor, retrieved SourceEmailLogEmailLogLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { func(ctx context.Context, exec bob.Executor, retrieved SourceEmailLogEmailLogLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
@ -1884,6 +2336,58 @@ func (os CommunicationSlice) LoadOpenedByUser(ctx context.Context, exec bob.Exec
return nil return nil
} }
// LoadOrganization loads the communication's Organization into the .R struct
func (o *Communication) LoadOrganization(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil {
return nil
}
// Reset the relationship
o.R.Organization = nil
related, err := o.Organization(mods...).One(ctx, exec)
if err != nil {
return err
}
related.R.Communications = CommunicationSlice{o}
o.R.Organization = related
return nil
}
// LoadOrganization loads the communication's Organization into the .R struct
func (os CommunicationSlice) LoadOrganization(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if len(os) == 0 {
return nil
}
organizations, err := os.Organization(mods...).All(ctx, exec)
if err != nil {
return err
}
for _, o := range os {
if o == nil {
continue
}
for _, rel := range organizations {
if !(o.OrganizationID == rel.ID) {
continue
}
rel.R.Communications = append(rel.R.Communications, o)
o.R.Organization = rel
break
}
}
return nil
}
// LoadResponseEmailLogEmailLog loads the communication's ResponseEmailLogEmailLog into the .R struct // LoadResponseEmailLogEmailLog loads the communication's ResponseEmailLogEmailLog into the .R struct
func (o *Communication) LoadResponseEmailLogEmailLog(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { func (o *Communication) LoadResponseEmailLogEmailLog(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil { if o == nil {
@ -2049,6 +2553,116 @@ func (os CommunicationSlice) LoadSetPendingByUser(ctx context.Context, exec bob.
return nil return nil
} }
// LoadSetPossibleIssueByUser loads the communication's SetPossibleIssueByUser into the .R struct
func (o *Communication) LoadSetPossibleIssueByUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil {
return nil
}
// Reset the relationship
o.R.SetPossibleIssueByUser = nil
related, err := o.SetPossibleIssueByUser(mods...).One(ctx, exec)
if err != nil {
return err
}
related.R.SetPossibleIssueByCommunications = CommunicationSlice{o}
o.R.SetPossibleIssueByUser = related
return nil
}
// LoadSetPossibleIssueByUser loads the communication's SetPossibleIssueByUser into the .R struct
func (os CommunicationSlice) LoadSetPossibleIssueByUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if len(os) == 0 {
return nil
}
users, err := os.SetPossibleIssueByUser(mods...).All(ctx, exec)
if err != nil {
return err
}
for _, o := range os {
if o == nil {
continue
}
for _, rel := range users {
if !o.SetPossibleIssueBy.IsValue() {
continue
}
if !(o.SetPossibleIssueBy.IsValue() && o.SetPossibleIssueBy.MustGet() == rel.ID) {
continue
}
rel.R.SetPossibleIssueByCommunications = append(rel.R.SetPossibleIssueByCommunications, o)
o.R.SetPossibleIssueByUser = rel
break
}
}
return nil
}
// LoadSetPossibleResolvedByUser loads the communication's SetPossibleResolvedByUser into the .R struct
func (o *Communication) LoadSetPossibleResolvedByUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil {
return nil
}
// Reset the relationship
o.R.SetPossibleResolvedByUser = nil
related, err := o.SetPossibleResolvedByUser(mods...).One(ctx, exec)
if err != nil {
return err
}
related.R.SetPossibleResolvedByCommunications = CommunicationSlice{o}
o.R.SetPossibleResolvedByUser = related
return nil
}
// LoadSetPossibleResolvedByUser loads the communication's SetPossibleResolvedByUser into the .R struct
func (os CommunicationSlice) LoadSetPossibleResolvedByUser(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if len(os) == 0 {
return nil
}
users, err := os.SetPossibleResolvedByUser(mods...).All(ctx, exec)
if err != nil {
return err
}
for _, o := range os {
if o == nil {
continue
}
for _, rel := range users {
if !o.SetPossibleResolvedBy.IsValue() {
continue
}
if !(o.SetPossibleResolvedBy.IsValue() && o.SetPossibleResolvedBy.MustGet() == rel.ID) {
continue
}
rel.R.SetPossibleResolvedByCommunications = append(rel.R.SetPossibleResolvedByCommunications, o)
o.R.SetPossibleResolvedByUser = rel
break
}
}
return nil
}
// LoadSourceEmailLogEmailLog loads the communication's SourceEmailLogEmailLog into the .R struct // LoadSourceEmailLogEmailLog loads the communication's SourceEmailLogEmailLog into the .R struct
func (o *Communication) LoadSourceEmailLogEmailLog(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { func (o *Communication) LoadSourceEmailLogEmailLog(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil { if o == nil {

View file

@ -78,6 +78,7 @@ type OrganizationsQuery = *psql.ViewQuery[*Organization, OrganizationSlice]
// organizationR is where relationships are stored. // organizationR is where relationships are stored.
type organizationR struct { type organizationR struct {
Communications CommunicationSlice // communication.communication_organization_id_fkey
EmailContacts CommsEmailContactSlice // district_subscription_email.district_subscription_email_email_contact_address_fkeydistrict_subscription_email.district_subscription_email_organization_id_fkey EmailContacts CommsEmailContactSlice // district_subscription_email.district_subscription_email_email_contact_address_fkeydistrict_subscription_email.district_subscription_email_organization_id_fkey
Phones CommsPhoneSlice // district_subscription_phone.district_subscription_phone_organization_id_fkeydistrict_subscription_phone.district_subscription_phone_phone_e164_fkey Phones CommsPhoneSlice // district_subscription_phone.district_subscription_phone_organization_id_fkeydistrict_subscription_phone.district_subscription_phone_phone_e164_fkey
Features FeatureSlice // feature.feature_organization_id_fkey Features FeatureSlice // feature.feature_organization_id_fkey
@ -972,6 +973,30 @@ func (o OrganizationSlice) ReloadAll(ctx context.Context, exec bob.Executor) err
return nil return nil
} }
// Communications starts a query for related objects on communication
func (o *Organization) Communications(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationsQuery {
return Communications.Query(append(mods,
sm.Where(Communications.Columns.OrganizationID.EQ(psql.Arg(o.ID))),
)...)
}
func (os OrganizationSlice) Communications(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationsQuery {
pkID := make(pgtypes.Array[int32], 0, len(os))
for _, o := range os {
if o == nil {
continue
}
pkID = append(pkID, o.ID)
}
PKArgExpr := psql.Select(sm.Columns(
psql.F("unnest", psql.Cast(psql.Arg(pkID), "integer[]")),
))
return Communications.Query(append(mods,
sm.Where(psql.Group(Communications.Columns.OrganizationID).OP("IN", PKArgExpr)),
)...)
}
// EmailContacts starts a query for related objects on comms.email_contact // EmailContacts starts a query for related objects on comms.email_contact
func (o *Organization) EmailContacts(mods ...bob.Mod[*dialect.SelectQuery]) CommsEmailContactsQuery { func (o *Organization) EmailContacts(mods ...bob.Mod[*dialect.SelectQuery]) CommsEmailContactsQuery {
return CommsEmailContacts.Query(append(mods, return CommsEmailContacts.Query(append(mods,
@ -1990,6 +2015,74 @@ func (os OrganizationSlice) User(mods ...bob.Mod[*dialect.SelectQuery]) UsersQue
)...) )...)
} }
func insertOrganizationCommunications0(ctx context.Context, exec bob.Executor, communications1 []*CommunicationSetter, organization0 *Organization) (CommunicationSlice, error) {
for i := range communications1 {
communications1[i].OrganizationID = omit.From(organization0.ID)
}
ret, err := Communications.Insert(bob.ToMods(communications1...)).All(ctx, exec)
if err != nil {
return ret, fmt.Errorf("insertOrganizationCommunications0: %w", err)
}
return ret, nil
}
func attachOrganizationCommunications0(ctx context.Context, exec bob.Executor, count int, communications1 CommunicationSlice, organization0 *Organization) (CommunicationSlice, error) {
setter := &CommunicationSetter{
OrganizationID: omit.From(organization0.ID),
}
err := communications1.UpdateAll(ctx, exec, *setter)
if err != nil {
return nil, fmt.Errorf("attachOrganizationCommunications0: %w", err)
}
return communications1, nil
}
func (organization0 *Organization) InsertCommunications(ctx context.Context, exec bob.Executor, related ...*CommunicationSetter) error {
if len(related) == 0 {
return nil
}
var err error
communications1, err := insertOrganizationCommunications0(ctx, exec, related, organization0)
if err != nil {
return err
}
organization0.R.Communications = append(organization0.R.Communications, communications1...)
for _, rel := range communications1 {
rel.R.Organization = organization0
}
return nil
}
func (organization0 *Organization) AttachCommunications(ctx context.Context, exec bob.Executor, related ...*Communication) error {
if len(related) == 0 {
return nil
}
var err error
communications1 := CommunicationSlice(related)
_, err = attachOrganizationCommunications0(ctx, exec, len(related), communications1, organization0)
if err != nil {
return err
}
organization0.R.Communications = append(organization0.R.Communications, communications1...)
for _, rel := range related {
rel.R.Organization = organization0
}
return nil
}
func attachOrganizationEmailContacts0(ctx context.Context, exec bob.Executor, count int, organization0 *Organization, commsEmailContacts2 CommsEmailContactSlice) (DistrictSubscriptionEmailSlice, error) { func attachOrganizationEmailContacts0(ctx context.Context, exec bob.Executor, count int, organization0 *Organization, commsEmailContacts2 CommsEmailContactSlice) (DistrictSubscriptionEmailSlice, error) {
setters := make([]*DistrictSubscriptionEmailSetter, count) setters := make([]*DistrictSubscriptionEmailSetter, count)
for i := range count { for i := range count {
@ -4928,6 +5021,20 @@ func (o *Organization) Preload(name string, retrieved any) error {
} }
switch name { switch name {
case "Communications":
rels, ok := retrieved.(CommunicationSlice)
if !ok {
return fmt.Errorf("organization cannot load %T as %q", retrieved, name)
}
o.R.Communications = rels
for _, rel := range rels {
if rel != nil {
rel.R.Organization = o
}
}
return nil
case "EmailContacts": case "EmailContacts":
rels, ok := retrieved.(CommsEmailContactSlice) rels, ok := retrieved.(CommsEmailContactSlice)
if !ok { if !ok {
@ -5528,6 +5635,7 @@ func buildOrganizationPreloader() organizationPreloader {
} }
type organizationThenLoader[Q orm.Loadable] struct { type organizationThenLoader[Q orm.Loadable] struct {
Communications func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
EmailContacts func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] EmailContacts func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
Phones func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] Phones func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
Features func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] Features func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
@ -5573,6 +5681,9 @@ type organizationThenLoader[Q orm.Loadable] struct {
} }
func buildOrganizationThenLoader[Q orm.Loadable]() organizationThenLoader[Q] { func buildOrganizationThenLoader[Q orm.Loadable]() organizationThenLoader[Q] {
type CommunicationsLoadInterface interface {
LoadCommunications(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
}
type EmailContactsLoadInterface interface { type EmailContactsLoadInterface interface {
LoadEmailContacts(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error LoadEmailContacts(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
} }
@ -5701,6 +5812,12 @@ func buildOrganizationThenLoader[Q orm.Loadable]() organizationThenLoader[Q] {
} }
return organizationThenLoader[Q]{ return organizationThenLoader[Q]{
Communications: thenLoadBuilder[Q](
"Communications",
func(ctx context.Context, exec bob.Executor, retrieved CommunicationsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
return retrieved.LoadCommunications(ctx, exec, mods...)
},
),
EmailContacts: thenLoadBuilder[Q]( EmailContacts: thenLoadBuilder[Q](
"EmailContacts", "EmailContacts",
func(ctx context.Context, exec bob.Executor, retrieved EmailContactsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { func(ctx context.Context, exec bob.Executor, retrieved EmailContactsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
@ -5956,6 +6073,67 @@ func buildOrganizationThenLoader[Q orm.Loadable]() organizationThenLoader[Q] {
} }
} }
// LoadCommunications loads the organization's Communications into the .R struct
func (o *Organization) LoadCommunications(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil {
return nil
}
// Reset the relationship
o.R.Communications = nil
related, err := o.Communications(mods...).All(ctx, exec)
if err != nil {
return err
}
for _, rel := range related {
rel.R.Organization = o
}
o.R.Communications = related
return nil
}
// LoadCommunications loads the organization's Communications into the .R struct
func (os OrganizationSlice) LoadCommunications(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if len(os) == 0 {
return nil
}
communications, err := os.Communications(mods...).All(ctx, exec)
if err != nil {
return err
}
for _, o := range os {
if o == nil {
continue
}
o.R.Communications = nil
}
for _, o := range os {
if o == nil {
continue
}
for _, rel := range communications {
if !(o.ID == rel.OrganizationID) {
continue
}
rel.R.Organization = o
o.R.Communications = append(o.R.Communications, rel)
}
}
return nil
}
// LoadEmailContacts loads the organization's EmailContacts into the .R struct // LoadEmailContacts loads the organization's EmailContacts into the .R struct
func (o *Organization) LoadEmailContacts(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { func (o *Organization) LoadEmailContacts(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil { if o == nil {

View file

@ -31,7 +31,7 @@ type PublicreportCompliance struct {
Comments string `db:"comments" ` Comments string `db:"comments" `
GateCode string `db:"gate_code" ` GateCode string `db:"gate_code" `
HasDog null.Val[bool] `db:"has_dog" ` HasDog null.Val[bool] `db:"has_dog" `
PermissionType enums.Permissionaccesstype `db:"permission_type" ` PermissionType enums.PublicreportPermissionaccesstype `db:"permission_type" `
ReportID int32 `db:"report_id,pk" ` ReportID int32 `db:"report_id,pk" `
ReportPhoneCanText null.Val[bool] `db:"report_phone_can_text" ` ReportPhoneCanText null.Val[bool] `db:"report_phone_can_text" `
WantsScheduled null.Val[bool] `db:"wants_scheduled" ` WantsScheduled null.Val[bool] `db:"wants_scheduled" `
@ -106,7 +106,7 @@ type PublicreportComplianceSetter struct {
Comments omit.Val[string] `db:"comments" ` Comments omit.Val[string] `db:"comments" `
GateCode omit.Val[string] `db:"gate_code" ` GateCode omit.Val[string] `db:"gate_code" `
HasDog omitnull.Val[bool] `db:"has_dog" ` HasDog omitnull.Val[bool] `db:"has_dog" `
PermissionType omit.Val[enums.Permissionaccesstype] `db:"permission_type" ` PermissionType omit.Val[enums.PublicreportPermissionaccesstype] `db:"permission_type" `
ReportID omit.Val[int32] `db:"report_id,pk" ` ReportID omit.Val[int32] `db:"report_id,pk" `
ReportPhoneCanText omitnull.Val[bool] `db:"report_phone_can_text" ` ReportPhoneCanText omitnull.Val[bool] `db:"report_phone_can_text" `
WantsScheduled omitnull.Val[bool] `db:"wants_scheduled" ` WantsScheduled omitnull.Val[bool] `db:"wants_scheduled" `
@ -633,7 +633,7 @@ type publicreportComplianceWhere[Q psql.Filterable] struct {
Comments psql.WhereMod[Q, string] Comments psql.WhereMod[Q, string]
GateCode psql.WhereMod[Q, string] GateCode psql.WhereMod[Q, string]
HasDog psql.WhereNullMod[Q, bool] HasDog psql.WhereNullMod[Q, bool]
PermissionType psql.WhereMod[Q, enums.Permissionaccesstype] PermissionType psql.WhereMod[Q, enums.PublicreportPermissionaccesstype]
ReportID psql.WhereMod[Q, int32] ReportID psql.WhereMod[Q, int32]
ReportPhoneCanText psql.WhereNullMod[Q, bool] ReportPhoneCanText psql.WhereNullMod[Q, bool]
WantsScheduled psql.WhereNullMod[Q, bool] WantsScheduled psql.WhereNullMod[Q, bool]
@ -651,7 +651,7 @@ func buildPublicreportComplianceWhere[Q psql.Filterable](cols publicreportCompli
Comments: psql.Where[Q, string](cols.Comments), Comments: psql.Where[Q, string](cols.Comments),
GateCode: psql.Where[Q, string](cols.GateCode), GateCode: psql.Where[Q, string](cols.GateCode),
HasDog: psql.WhereNull[Q, bool](cols.HasDog), HasDog: psql.WhereNull[Q, bool](cols.HasDog),
PermissionType: psql.Where[Q, enums.Permissionaccesstype](cols.PermissionType), PermissionType: psql.Where[Q, enums.PublicreportPermissionaccesstype](cols.PermissionType),
ReportID: psql.Where[Q, int32](cols.ReportID), ReportID: psql.Where[Q, int32](cols.ReportID),
ReportPhoneCanText: psql.WhereNull[Q, bool](cols.ReportPhoneCanText), ReportPhoneCanText: psql.WhereNull[Q, bool](cols.ReportPhoneCanText),
WantsScheduled: psql.WhereNull[Q, bool](cols.WantsScheduled), WantsScheduled: psql.WhereNull[Q, bool](cols.WantsScheduled),

View file

@ -65,6 +65,8 @@ type userR struct {
InvalidatedByCommunications CommunicationSlice // communication.communication_invalidated_by_fkey InvalidatedByCommunications CommunicationSlice // communication.communication_invalidated_by_fkey
OpenedByCommunications CommunicationSlice // communication.communication_opened_by_fkey OpenedByCommunications CommunicationSlice // communication.communication_opened_by_fkey
SetPendingByCommunications CommunicationSlice // communication.communication_set_pending_by_fkey SetPendingByCommunications CommunicationSlice // communication.communication_set_pending_by_fkey
SetPossibleIssueByCommunications CommunicationSlice // communication.communication_set_possible_issue_by_fkey
SetPossibleResolvedByCommunications CommunicationSlice // communication.communication_set_possible_resolved_by_fkey
CreatorComplianceReportRequests ComplianceReportRequestSlice // compliance_report_request.compliance_report_request_creator_fkey CreatorComplianceReportRequests ComplianceReportRequestSlice // compliance_report_request.compliance_report_request_creator_fkey
CreatorFeatures FeatureSlice // feature.feature_creator_id_fkey CreatorFeatures FeatureSlice // feature.feature_creator_id_fkey
CommitterFiles FileuploadFileSlice // fileupload.file.file_committer_fkey CommitterFiles FileuploadFileSlice // fileupload.file.file_committer_fkey
@ -866,6 +868,54 @@ func (os UserSlice) SetPendingByCommunications(mods ...bob.Mod[*dialect.SelectQu
)...) )...)
} }
// SetPossibleIssueByCommunications starts a query for related objects on communication
func (o *User) SetPossibleIssueByCommunications(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationsQuery {
return Communications.Query(append(mods,
sm.Where(Communications.Columns.SetPossibleIssueBy.EQ(psql.Arg(o.ID))),
)...)
}
func (os UserSlice) SetPossibleIssueByCommunications(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationsQuery {
pkID := make(pgtypes.Array[int32], 0, len(os))
for _, o := range os {
if o == nil {
continue
}
pkID = append(pkID, o.ID)
}
PKArgExpr := psql.Select(sm.Columns(
psql.F("unnest", psql.Cast(psql.Arg(pkID), "integer[]")),
))
return Communications.Query(append(mods,
sm.Where(psql.Group(Communications.Columns.SetPossibleIssueBy).OP("IN", PKArgExpr)),
)...)
}
// SetPossibleResolvedByCommunications starts a query for related objects on communication
func (o *User) SetPossibleResolvedByCommunications(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationsQuery {
return Communications.Query(append(mods,
sm.Where(Communications.Columns.SetPossibleResolvedBy.EQ(psql.Arg(o.ID))),
)...)
}
func (os UserSlice) SetPossibleResolvedByCommunications(mods ...bob.Mod[*dialect.SelectQuery]) CommunicationsQuery {
pkID := make(pgtypes.Array[int32], 0, len(os))
for _, o := range os {
if o == nil {
continue
}
pkID = append(pkID, o.ID)
}
PKArgExpr := psql.Select(sm.Columns(
psql.F("unnest", psql.Cast(psql.Arg(pkID), "integer[]")),
))
return Communications.Query(append(mods,
sm.Where(psql.Group(Communications.Columns.SetPossibleResolvedBy).OP("IN", PKArgExpr)),
)...)
}
// CreatorComplianceReportRequests starts a query for related objects on compliance_report_request // CreatorComplianceReportRequests starts a query for related objects on compliance_report_request
func (o *User) CreatorComplianceReportRequests(mods ...bob.Mod[*dialect.SelectQuery]) ComplianceReportRequestsQuery { func (o *User) CreatorComplianceReportRequests(mods ...bob.Mod[*dialect.SelectQuery]) ComplianceReportRequestsQuery {
return ComplianceReportRequests.Query(append(mods, return ComplianceReportRequests.Query(append(mods,
@ -1806,6 +1856,142 @@ func (user0 *User) AttachSetPendingByCommunications(ctx context.Context, exec bo
return nil return nil
} }
func insertUserSetPossibleIssueByCommunications0(ctx context.Context, exec bob.Executor, communications1 []*CommunicationSetter, user0 *User) (CommunicationSlice, error) {
for i := range communications1 {
communications1[i].SetPossibleIssueBy = omitnull.From(user0.ID)
}
ret, err := Communications.Insert(bob.ToMods(communications1...)).All(ctx, exec)
if err != nil {
return ret, fmt.Errorf("insertUserSetPossibleIssueByCommunications0: %w", err)
}
return ret, nil
}
func attachUserSetPossibleIssueByCommunications0(ctx context.Context, exec bob.Executor, count int, communications1 CommunicationSlice, user0 *User) (CommunicationSlice, error) {
setter := &CommunicationSetter{
SetPossibleIssueBy: omitnull.From(user0.ID),
}
err := communications1.UpdateAll(ctx, exec, *setter)
if err != nil {
return nil, fmt.Errorf("attachUserSetPossibleIssueByCommunications0: %w", err)
}
return communications1, nil
}
func (user0 *User) InsertSetPossibleIssueByCommunications(ctx context.Context, exec bob.Executor, related ...*CommunicationSetter) error {
if len(related) == 0 {
return nil
}
var err error
communications1, err := insertUserSetPossibleIssueByCommunications0(ctx, exec, related, user0)
if err != nil {
return err
}
user0.R.SetPossibleIssueByCommunications = append(user0.R.SetPossibleIssueByCommunications, communications1...)
for _, rel := range communications1 {
rel.R.SetPossibleIssueByUser = user0
}
return nil
}
func (user0 *User) AttachSetPossibleIssueByCommunications(ctx context.Context, exec bob.Executor, related ...*Communication) error {
if len(related) == 0 {
return nil
}
var err error
communications1 := CommunicationSlice(related)
_, err = attachUserSetPossibleIssueByCommunications0(ctx, exec, len(related), communications1, user0)
if err != nil {
return err
}
user0.R.SetPossibleIssueByCommunications = append(user0.R.SetPossibleIssueByCommunications, communications1...)
for _, rel := range related {
rel.R.SetPossibleIssueByUser = user0
}
return nil
}
func insertUserSetPossibleResolvedByCommunications0(ctx context.Context, exec bob.Executor, communications1 []*CommunicationSetter, user0 *User) (CommunicationSlice, error) {
for i := range communications1 {
communications1[i].SetPossibleResolvedBy = omitnull.From(user0.ID)
}
ret, err := Communications.Insert(bob.ToMods(communications1...)).All(ctx, exec)
if err != nil {
return ret, fmt.Errorf("insertUserSetPossibleResolvedByCommunications0: %w", err)
}
return ret, nil
}
func attachUserSetPossibleResolvedByCommunications0(ctx context.Context, exec bob.Executor, count int, communications1 CommunicationSlice, user0 *User) (CommunicationSlice, error) {
setter := &CommunicationSetter{
SetPossibleResolvedBy: omitnull.From(user0.ID),
}
err := communications1.UpdateAll(ctx, exec, *setter)
if err != nil {
return nil, fmt.Errorf("attachUserSetPossibleResolvedByCommunications0: %w", err)
}
return communications1, nil
}
func (user0 *User) InsertSetPossibleResolvedByCommunications(ctx context.Context, exec bob.Executor, related ...*CommunicationSetter) error {
if len(related) == 0 {
return nil
}
var err error
communications1, err := insertUserSetPossibleResolvedByCommunications0(ctx, exec, related, user0)
if err != nil {
return err
}
user0.R.SetPossibleResolvedByCommunications = append(user0.R.SetPossibleResolvedByCommunications, communications1...)
for _, rel := range communications1 {
rel.R.SetPossibleResolvedByUser = user0
}
return nil
}
func (user0 *User) AttachSetPossibleResolvedByCommunications(ctx context.Context, exec bob.Executor, related ...*Communication) error {
if len(related) == 0 {
return nil
}
var err error
communications1 := CommunicationSlice(related)
_, err = attachUserSetPossibleResolvedByCommunications0(ctx, exec, len(related), communications1, user0)
if err != nil {
return err
}
user0.R.SetPossibleResolvedByCommunications = append(user0.R.SetPossibleResolvedByCommunications, communications1...)
for _, rel := range related {
rel.R.SetPossibleResolvedByUser = user0
}
return nil
}
func insertUserCreatorComplianceReportRequests0(ctx context.Context, exec bob.Executor, complianceReportRequests1 []*ComplianceReportRequestSetter, user0 *User) (ComplianceReportRequestSlice, error) { func insertUserCreatorComplianceReportRequests0(ctx context.Context, exec bob.Executor, complianceReportRequests1 []*ComplianceReportRequestSetter, user0 *User) (ComplianceReportRequestSlice, error) {
for i := range complianceReportRequests1 { for i := range complianceReportRequests1 {
complianceReportRequests1[i].Creator = omit.From(user0.ID) complianceReportRequests1[i].Creator = omit.From(user0.ID)
@ -3608,6 +3794,34 @@ func (o *User) Preload(name string, retrieved any) error {
} }
} }
return nil return nil
case "SetPossibleIssueByCommunications":
rels, ok := retrieved.(CommunicationSlice)
if !ok {
return fmt.Errorf("user cannot load %T as %q", retrieved, name)
}
o.R.SetPossibleIssueByCommunications = rels
for _, rel := range rels {
if rel != nil {
rel.R.SetPossibleIssueByUser = o
}
}
return nil
case "SetPossibleResolvedByCommunications":
rels, ok := retrieved.(CommunicationSlice)
if !ok {
return fmt.Errorf("user cannot load %T as %q", retrieved, name)
}
o.R.SetPossibleResolvedByCommunications = rels
for _, rel := range rels {
if rel != nil {
rel.R.SetPossibleResolvedByUser = o
}
}
return nil
case "CreatorComplianceReportRequests": case "CreatorComplianceReportRequests":
rels, ok := retrieved.(ComplianceReportRequestSlice) rels, ok := retrieved.(ComplianceReportRequestSlice)
if !ok { if !ok {
@ -3989,6 +4203,8 @@ type userThenLoader[Q orm.Loadable] struct {
InvalidatedByCommunications func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] InvalidatedByCommunications func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
OpenedByCommunications func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] OpenedByCommunications func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
SetPendingByCommunications func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] SetPendingByCommunications func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
SetPossibleIssueByCommunications func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
SetPossibleResolvedByCommunications func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
CreatorComplianceReportRequests func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] CreatorComplianceReportRequests func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
CreatorFeatures func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] CreatorFeatures func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
CommitterFiles func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q] CommitterFiles func(...bob.Mod[*dialect.SelectQuery]) orm.Loader[Q]
@ -4032,6 +4248,12 @@ func buildUserThenLoader[Q orm.Loadable]() userThenLoader[Q] {
type SetPendingByCommunicationsLoadInterface interface { type SetPendingByCommunicationsLoadInterface interface {
LoadSetPendingByCommunications(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error LoadSetPendingByCommunications(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
} }
type SetPossibleIssueByCommunicationsLoadInterface interface {
LoadSetPossibleIssueByCommunications(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
}
type SetPossibleResolvedByCommunicationsLoadInterface interface {
LoadSetPossibleResolvedByCommunications(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
}
type CreatorComplianceReportRequestsLoadInterface interface { type CreatorComplianceReportRequestsLoadInterface interface {
LoadCreatorComplianceReportRequests(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error LoadCreatorComplianceReportRequests(context.Context, bob.Executor, ...bob.Mod[*dialect.SelectQuery]) error
} }
@ -4139,6 +4361,18 @@ func buildUserThenLoader[Q orm.Loadable]() userThenLoader[Q] {
return retrieved.LoadSetPendingByCommunications(ctx, exec, mods...) return retrieved.LoadSetPendingByCommunications(ctx, exec, mods...)
}, },
), ),
SetPossibleIssueByCommunications: thenLoadBuilder[Q](
"SetPossibleIssueByCommunications",
func(ctx context.Context, exec bob.Executor, retrieved SetPossibleIssueByCommunicationsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
return retrieved.LoadSetPossibleIssueByCommunications(ctx, exec, mods...)
},
),
SetPossibleResolvedByCommunications: thenLoadBuilder[Q](
"SetPossibleResolvedByCommunications",
func(ctx context.Context, exec bob.Executor, retrieved SetPossibleResolvedByCommunicationsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
return retrieved.LoadSetPossibleResolvedByCommunications(ctx, exec, mods...)
},
),
CreatorComplianceReportRequests: thenLoadBuilder[Q]( CreatorComplianceReportRequests: thenLoadBuilder[Q](
"CreatorComplianceReportRequests", "CreatorComplianceReportRequests",
func(ctx context.Context, exec bob.Executor, retrieved CreatorComplianceReportRequestsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error { func(ctx context.Context, exec bob.Executor, retrieved CreatorComplianceReportRequestsLoadInterface, mods ...bob.Mod[*dialect.SelectQuery]) error {
@ -4612,6 +4846,134 @@ func (os UserSlice) LoadSetPendingByCommunications(ctx context.Context, exec bob
return nil return nil
} }
// LoadSetPossibleIssueByCommunications loads the user's SetPossibleIssueByCommunications into the .R struct
func (o *User) LoadSetPossibleIssueByCommunications(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil {
return nil
}
// Reset the relationship
o.R.SetPossibleIssueByCommunications = nil
related, err := o.SetPossibleIssueByCommunications(mods...).All(ctx, exec)
if err != nil {
return err
}
for _, rel := range related {
rel.R.SetPossibleIssueByUser = o
}
o.R.SetPossibleIssueByCommunications = related
return nil
}
// LoadSetPossibleIssueByCommunications loads the user's SetPossibleIssueByCommunications into the .R struct
func (os UserSlice) LoadSetPossibleIssueByCommunications(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if len(os) == 0 {
return nil
}
communications, err := os.SetPossibleIssueByCommunications(mods...).All(ctx, exec)
if err != nil {
return err
}
for _, o := range os {
if o == nil {
continue
}
o.R.SetPossibleIssueByCommunications = nil
}
for _, o := range os {
if o == nil {
continue
}
for _, rel := range communications {
if !rel.SetPossibleIssueBy.IsValue() {
continue
}
if !(rel.SetPossibleIssueBy.IsValue() && o.ID == rel.SetPossibleIssueBy.MustGet()) {
continue
}
rel.R.SetPossibleIssueByUser = o
o.R.SetPossibleIssueByCommunications = append(o.R.SetPossibleIssueByCommunications, rel)
}
}
return nil
}
// LoadSetPossibleResolvedByCommunications loads the user's SetPossibleResolvedByCommunications into the .R struct
func (o *User) LoadSetPossibleResolvedByCommunications(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil {
return nil
}
// Reset the relationship
o.R.SetPossibleResolvedByCommunications = nil
related, err := o.SetPossibleResolvedByCommunications(mods...).All(ctx, exec)
if err != nil {
return err
}
for _, rel := range related {
rel.R.SetPossibleResolvedByUser = o
}
o.R.SetPossibleResolvedByCommunications = related
return nil
}
// LoadSetPossibleResolvedByCommunications loads the user's SetPossibleResolvedByCommunications into the .R struct
func (os UserSlice) LoadSetPossibleResolvedByCommunications(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if len(os) == 0 {
return nil
}
communications, err := os.SetPossibleResolvedByCommunications(mods...).All(ctx, exec)
if err != nil {
return err
}
for _, o := range os {
if o == nil {
continue
}
o.R.SetPossibleResolvedByCommunications = nil
}
for _, o := range os {
if o == nil {
continue
}
for _, rel := range communications {
if !rel.SetPossibleResolvedBy.IsValue() {
continue
}
if !(rel.SetPossibleResolvedBy.IsValue() && o.ID == rel.SetPossibleResolvedBy.MustGet()) {
continue
}
rel.R.SetPossibleResolvedByUser = o
o.R.SetPossibleResolvedByCommunications = append(o.R.SetPossibleResolvedByCommunications, rel)
}
}
return nil
}
// LoadCreatorComplianceReportRequests loads the user's CreatorComplianceReportRequests into the .R struct // LoadCreatorComplianceReportRequests loads the user's CreatorComplianceReportRequests into the .R struct
func (o *User) LoadCreatorComplianceReportRequests(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error { func (o *User) LoadCreatorComplianceReportRequests(ctx context.Context, exec bob.Executor, mods ...bob.Mod[*dialect.SelectQuery]) error {
if o == nil { if o == nil {

View file

@ -18,6 +18,13 @@ func CommunicationInsert(ctx context.Context, txn bob.Tx, m *model.Communication
RETURNING(table.Communication.AllColumns) RETURNING(table.Communication.AllColumns)
return db.ExecuteOne[model.Communication](ctx, statement) return db.ExecuteOne[model.Communication](ctx, statement)
} }
func CommunicationFromID(ctx context.Context, comm_id int64) (*model.Communication, error) {
statement := table.Communication.SELECT(
table.Communication.AllColumns,
).FROM(table.Communication).
WHERE(table.Communication.ID.EQ(postgres.Int(comm_id)))
return db.ExecuteOne[model.Communication](ctx, statement)
}
func CommunicationsFromOrganization(ctx context.Context, org_id int64) ([]*model.Communication, error) { func CommunicationsFromOrganization(ctx context.Context, org_id int64) ([]*model.Communication, error) {
statement := table.Communication.SELECT( statement := table.Communication.SELECT(
table.Communication.AllColumns, table.Communication.AllColumns,
@ -25,3 +32,35 @@ func CommunicationsFromOrganization(ctx context.Context, org_id int64) ([]*model
WHERE(table.Communication.OrganizationID.EQ(postgres.Int(org_id))) WHERE(table.Communication.OrganizationID.EQ(postgres.Int(org_id)))
return db.ExecuteMany[model.Communication](ctx, statement) return db.ExecuteMany[model.Communication](ctx, statement)
} }
func CommunicationMarkInvalid(ctx context.Context, org_id int64, user_id int64, comm_id int64) error {
statement := table.Communication.UPDATE().
SET(table.Communication.Invalidated.SET(postgres.LOCALTIMESTAMP())).
SET(table.Communication.InvalidatedBy.SET(postgres.Int(user_id))).
WHERE(table.Communication.OrganizationID.EQ(postgres.Int(org_id)).AND(
table.Communication.ID.EQ(postgres.Int(comm_id))))
return db.ExecuteNone(ctx, statement)
}
func CommunicationMarkPendingResponse(ctx context.Context, org_id int64, user_id int64, comm_id int64) error {
statement := table.Communication.UPDATE().
SET(table.Communication.SetPending.SET(postgres.LOCALTIMESTAMP())).
SET(table.Communication.SetPendingBy.SET(postgres.Int(user_id))).
WHERE(table.Communication.OrganizationID.EQ(postgres.Int(org_id)).AND(
table.Communication.ID.EQ(postgres.Int(comm_id))))
return db.ExecuteNone(ctx, statement)
}
func CommunicationMarkPossibleIssue(ctx context.Context, org_id int64, user_id int64, comm_id int64) error {
statement := table.Communication.UPDATE().
SET(table.Communication.SetPossibleIssue.SET(postgres.LOCALTIMESTAMP())).
SET(table.Communication.SetPossibleIssueBy.SET(postgres.Int(user_id))).
WHERE(table.Communication.OrganizationID.EQ(postgres.Int(org_id)).AND(
table.Communication.ID.EQ(postgres.Int(comm_id))))
return db.ExecuteNone(ctx, statement)
}
func CommunicationMarkPossibleResolved(ctx context.Context, org_id int64, user_id int64, comm_id int64) error {
statement := table.Communication.UPDATE().
SET(table.Communication.SetPossibleResolved.SET(postgres.LOCALTIMESTAMP())).
SET(table.Communication.SetPossibleResolvedBy.SET(postgres.Int(user_id))).
WHERE(table.Communication.OrganizationID.EQ(postgres.Int(org_id)).AND(
table.Communication.ID.EQ(postgres.Int(comm_id))))
return db.ExecuteNone(ctx, statement)
}

View file

@ -3,6 +3,7 @@ package html
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/Gleipnir-Technology/nidus-sync/lint"
"github.com/Gleipnir-Technology/nidus-sync/platform" "github.com/Gleipnir-Technology/nidus-sync/platform"
"github.com/Gleipnir-Technology/nidus-sync/platform/file" "github.com/Gleipnir-Technology/nidus-sync/platform/file"
"github.com/google/uuid" "github.com/google/uuid"
@ -21,7 +22,7 @@ func ExtractImageUpload(headers *multipart.FileHeader) (upload platform.ImageUpl
if err != nil { if err != nil {
return upload, fmt.Errorf("Failed to open header: %w", err) return upload, fmt.Errorf("Failed to open header: %w", err)
} }
defer f.Close() defer lint.LogOnErr(f.Close, "close headers")
file_bytes, err := io.ReadAll(f) file_bytes, err := io.ReadAll(f)
content_type := http.DetectContentType(file_bytes) content_type := http.DetectContentType(file_bytes)

View file

@ -5,6 +5,8 @@ import (
"fmt" "fmt"
"net/url" "net/url"
"time" "time"
"github.com/Gleipnir-Technology/nidus-sync/lint"
) )
// TasksListResponse represents the response from the /api/tasks endpoint // TasksListResponse represents the response from the /api/tasks endpoint
@ -131,7 +133,7 @@ func (c *Client) ListTasks(options *TasksListOptions) (*TasksListResponse, error
if err != nil { if err != nil {
return nil, fmt.Errorf("Failed to request %s: %v", path, err) return nil, fmt.Errorf("Failed to request %s: %v", path, err)
} }
defer resp.Body.Close() defer lint.LogOnErr(resp.Body.Close, "close response body")
// Parse response // Parse response
var tasksResponse TasksListResponse var tasksResponse TasksListResponse

View file

@ -4,6 +4,8 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"time" "time"
"github.com/Gleipnir-Technology/nidus-sync/lint"
) )
// ProjectsResponse represents the response from the /api/projects endpoint // ProjectsResponse represents the response from the /api/projects endpoint
@ -114,7 +116,7 @@ func (c *Client) Projects() (*ProjectsResponse, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("Failed to GET /api/projects: %w", err) return nil, fmt.Errorf("Failed to GET /api/projects: %w", err)
} }
defer resp.Body.Close() defer lint.LogOnErr(resp.Body.Close, "resp.Body.Close")
// Parse response // Parse response
var projects ProjectsResponse var projects ProjectsResponse

View file

@ -4,6 +4,8 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"time" "time"
"github.com/Gleipnir-Technology/nidus-sync/lint"
) )
// AnnotationRequest represents the request body for creating a draft // AnnotationRequest represents the request body for creating a draft
@ -63,7 +65,7 @@ func (c *Client) CreateAnnotation(taskID int, annotation *AnnotationRequest) (*A
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err) return nil, fmt.Errorf("failed to create request: %w", err)
} }
defer resp.Body.Close() defer lint.LogOnErr(resp.Body.Close, "close resp body")
// Parse response // Parse response
var createdAnnotation Annotation var createdAnnotation Annotation

25
lint/error.go Normal file
View file

@ -0,0 +1,25 @@
package lint
import (
"context"
"github.com/rs/zerolog/log"
)
type Errorable = func() error
func LogOnErr(f Errorable, msg string) {
e := f()
if e != nil {
log.Error().Err(e).Msg(msg)
}
}
type ErrorableCtx = func(context.Context) error
func LogOnErrCtx(f ErrorableCtx, ctx context.Context, msg string) {
e := f(ctx)
if e != nil {
log.Error().Err(e).Msg(msg)
}
}

18
main.go
View file

@ -16,6 +16,7 @@ import (
"github.com/Gleipnir-Technology/nidus-sync/config" "github.com/Gleipnir-Technology/nidus-sync/config"
"github.com/Gleipnir-Technology/nidus-sync/db" "github.com/Gleipnir-Technology/nidus-sync/db"
"github.com/Gleipnir-Technology/nidus-sync/html" "github.com/Gleipnir-Technology/nidus-sync/html"
"github.com/Gleipnir-Technology/nidus-sync/lint"
"github.com/Gleipnir-Technology/nidus-sync/llm" "github.com/Gleipnir-Technology/nidus-sync/llm"
"github.com/Gleipnir-Technology/nidus-sync/middleware" "github.com/Gleipnir-Technology/nidus-sync/middleware"
"github.com/Gleipnir-Technology/nidus-sync/platform" "github.com/Gleipnir-Technology/nidus-sync/platform"
@ -71,7 +72,7 @@ func main() {
log.Fatal().Err(err).Msg("Failed to create sentry writer") log.Fatal().Err(err).Msg("Failed to create sentry writer")
os.Exit(2) os.Exit(2)
} }
defer sentryWriter.Close() defer lint.LogOnErr(sentryWriter.Close, "close sentry writer")
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
log.Logger = log.Output(zerolog.MultiLevelWriter(zerolog.ConsoleWriter{Out: os.Stderr}, sentryWriter)) log.Logger = log.Output(zerolog.MultiLevelWriter(zerolog.ConsoleWriter{Out: os.Stderr}, sentryWriter))
@ -84,8 +85,14 @@ func main() {
// Defer cleanup in reverse order - these will execute LAST (LIFO) // Defer cleanup in reverse order - these will execute LAST (LIFO)
defer func() { defer func() {
log.Info().Msg("Final cleanup") log.Info().Msg("Final cleanup")
os.Stderr.Sync() err = os.Stderr.Sync()
sentryWriter.Close() if err != nil {
log.Error().Err(err).Msg("sync stderr")
}
err = sentryWriter.Close()
if err != nil {
log.Error().Err(err).Msg("close sentrywriter")
}
sentry.Flush(2 * time.Second) sentry.Flush(2 * time.Second)
}() }()
@ -183,7 +190,10 @@ func main() {
<-signalCh <-signalCh
log.Info().Msg("Received shutdown signal, shutting down...") log.Info().Msg("Received shutdown signal, shutting down...")
// Ensure logs are flushed // Ensure logs are flushed
os.Stderr.Sync() err = os.Stderr.Sync()
if err != nil {
log.Error().Err(err).Msg("stderr sync")
}
platform.EventShutdown() platform.EventShutdown()
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 30*time.Second) shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 30*time.Second)

View file

@ -51,7 +51,10 @@ func init() {
var buf [12]byte var buf [12]byte
var b64 string var b64 string
for len(b64) < 10 { for len(b64) < 10 {
rand.Read(buf[:]) _, err = rand.Read(buf[:])
if err != nil {
panic("failed to rand.Read")
}
b64 = base64.StdEncoding.EncodeToString(buf[:]) b64 = base64.StdEncoding.EncodeToString(buf[:])
b64 = strings.NewReplacer("+", "", "/", "").Replace(b64) b64 = strings.NewReplacer("+", "", "/", "").Replace(b64)
} }

View file

@ -52,12 +52,19 @@ func init() {
} }
// colorWrite // colorWrite
func cW(w io.Writer, useColor bool, color []byte, s string, args ...interface{}) { func cW(w io.Writer, useColor bool, color []byte, s string, args ...interface{}) error {
if IsTTY && useColor { if IsTTY && useColor {
w.Write(color) _, err := w.Write(color)
if err != nil {
return fmt.Errorf("write color: %w", err)
}
} }
fmt.Fprintf(w, s, args...) fmt.Fprintf(w, s, args...)
if IsTTY && useColor { if IsTTY && useColor {
w.Write(reset) _, err := w.Write(reset)
if err != nil {
return fmt.Errorf("write color: %w", err)
} }
}
return nil
} }

View file

@ -8,6 +8,7 @@ import (
"os" "os"
"time" "time"
"github.com/Gleipnir-Technology/nidus-sync/lint"
"github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials" "github.com/minio/minio-go/v7/pkg/credentials"
) )
@ -66,7 +67,7 @@ func (minioClient *Client) UploadFile(bucketName string, filePath string, upload
if err != nil { if err != nil {
return fmt.Errorf("Failed to open file %s to upload: %v", filePath, err) return fmt.Errorf("Failed to open file %s to upload: %v", filePath, err)
} }
defer file.Close() defer lint.LogOnErr(file.Close, "close file")
// Upload the file // Upload the file
_, err = minioClient.client.FPutObject(context.Background(), bucketName, uploadPath, filePath, minio.PutObjectOptions{}) _, err = minioClient.client.FPutObject(context.Background(), bucketName, uploadPath, filePath, minio.PutObjectOptions{})

View file

@ -37,6 +37,7 @@ import (
"github.com/Gleipnir-Technology/nidus-sync/db/types" "github.com/Gleipnir-Technology/nidus-sync/db/types"
"github.com/Gleipnir-Technology/nidus-sync/debug" "github.com/Gleipnir-Technology/nidus-sync/debug"
"github.com/Gleipnir-Technology/nidus-sync/h3utils" "github.com/Gleipnir-Technology/nidus-sync/h3utils"
"github.com/Gleipnir-Technology/nidus-sync/lint"
"github.com/Gleipnir-Technology/nidus-sync/platform/oauth" "github.com/Gleipnir-Technology/nidus-sync/platform/oauth"
"github.com/aarondl/opt/omit" "github.com/aarondl/opt/omit"
"github.com/aarondl/opt/omitnull" "github.com/aarondl/opt/omitnull"
@ -170,7 +171,7 @@ func downloadFieldseekerSchema(ctx context.Context, fieldseekerClient *fieldseek
log.Error().Err(err).Msg("Failed to open output") log.Error().Err(err).Msg("Failed to open output")
return return
} }
defer output.Close() defer lint.LogOnErr(output.Close, "close schema output file")
schema, err := fieldseekerClient.SchemaRaw(ctx, uint(i)) schema, err := fieldseekerClient.SchemaRaw(ctx, uint(i))
if err != nil { if err != nil {
log.Error().Err(err).Msg("Failed to get schema") log.Error().Err(err).Msg("Failed to get schema")
@ -212,7 +213,10 @@ func generateCodeChallenge(codeVerifier string) string {
// Generate a random code verifier for PKCE // Generate a random code verifier for PKCE
func generateCodeVerifier() string { func generateCodeVerifier() string {
bytes := make([]byte, 64) // 64 bytes = 512 bits bytes := make([]byte, 64) // 64 bytes = 512 bits
rand.Read(bytes) _, err := rand.Read(bytes)
if err != nil {
return ""
}
return base64.RawURLEncoding.EncodeToString(bytes) return base64.RawURLEncoding.EncodeToString(bytes)
} }

View file

@ -10,3 +10,25 @@ import (
func CommunicationsForOrganization(ctx context.Context, org_id int64) ([]*model.Communication, error) { func CommunicationsForOrganization(ctx context.Context, org_id int64) ([]*model.Communication, error) {
return querypublic.CommunicationsFromOrganization(ctx, org_id) return querypublic.CommunicationsFromOrganization(ctx, org_id)
} }
func CommunicationFromID(ctx context.Context, user User, comm_id int64) (*model.Communication, error) {
comm, err := querypublic.CommunicationFromID(ctx, comm_id)
if err != nil {
return nil, err
}
if comm.OrganizationID != user.Organization.ID {
return nil, nil
}
return comm, nil
}
func CommunicationMarkInvalid(ctx context.Context, user User, comm_id int64) error {
return querypublic.CommunicationMarkInvalid(ctx, int64(user.Organization.ID), int64(user.ID), comm_id)
}
func CommunicationMarkPendingResponse(ctx context.Context, user User, comm_id int64) error {
return querypublic.CommunicationMarkPendingResponse(ctx, int64(user.Organization.ID), int64(user.ID), comm_id)
}
func CommunicationMarkPossibleIssue(ctx context.Context, user User, comm_id int64) error {
return querypublic.CommunicationMarkPossibleIssue(ctx, int64(user.Organization.ID), int64(user.ID), comm_id)
}
func CommunicationMarkPossibleResolved(ctx context.Context, user User, comm_id int64) error {
return querypublic.CommunicationMarkPossibleResolved(ctx, int64(user.Organization.ID), int64(user.ID), comm_id)
}

View file

@ -256,9 +256,12 @@ func importCSV[T any](ctx context.Context, file_id int32, parser csvParserFunc[T
return fmt.Errorf("process parsed file: %w", err) return fmt.Errorf("process parsed file: %w", err)
} }
file.Update(ctx, txn, &models.FileuploadFileSetter{ err = file.Update(ctx, txn, &models.FileuploadFileSetter{
Status: omit.From(enums.FileuploadFilestatustypeParsed), Status: omit.From(enums.FileuploadFilestatustypeParsed),
}) })
if err != nil {
return fmt.Errorf("update: %w", err)
}
log.Info().Int32("file.ID", file.ID).Msg("Set file to parsed") log.Info().Int32("file.ID", file.ID).Msg("Set file to parsed")
txn.Commit(ctx) txn.Commit(ctx)
return nil return nil

View file

@ -187,9 +187,12 @@ func parseCSVPoollist(ctx context.Context, txn bob.Tx, f *models.FileuploadFile,
missing_headers := missingRequiredHeaders(header_types) missing_headers := missingRequiredHeaders(header_types)
for _, mh := range missing_headers { for _, mh := range missing_headers {
errorMissingHeader(ctx, txn, c, mh) errorMissingHeader(ctx, txn, c, mh)
f.Update(ctx, txn, &models.FileuploadFileSetter{ err = f.Update(ctx, txn, &models.FileuploadFileSetter{
Status: omit.From(enums.FileuploadFilestatustypeError), Status: omit.From(enums.FileuploadFilestatustypeError),
}) })
if err != nil {
return pools, fmt.Errorf("update: %w", err)
}
return pools, nil return pools, nil
} }
for i, header_name := range header_names { for i, header_name := range header_names {
@ -279,7 +282,11 @@ func parseCSVPoollist(ctx context.Context, txn bob.Tx, f *models.FileuploadFile,
addError(ctx, txn, c, int32(line_number), int32(i), fmt.Sprintf("'%s' is not a phone number that we recognize. Ideally it should be of the form '+12223334444'", col)) addError(ctx, txn, c, int32(line_number), int32(i), fmt.Sprintf("'%s' is not a phone number that we recognize. Ideally it should be of the form '+12223334444'", col))
continue continue
} }
text.EnsureInDB(ctx, txn, *phone) err = text.EnsureInDB(ctx, txn, *phone)
if err != nil {
log.Error().Err(err).Str("phone", col).Msg("ensure in DB failure")
continue
}
setter.PropertyOwnerPhoneE164 = omitnull.From(phone.PhoneString()) setter.PropertyOwnerPhoneE164 = omitnull.From(phone.PhoneString())
case headerPoolResidentOwned: case headerPoolResidentOwned:
boolValue, err := parseBool(col) boolValue, err := parseBool(col)
@ -294,7 +301,11 @@ func parseCSVPoollist(ctx context.Context, txn bob.Tx, f *models.FileuploadFile,
addError(ctx, txn, c, int32(line_number), int32(i), fmt.Sprintf("'%s' is not a phone number that we recognize. Ideally it should be of the form '+12223334444'", col)) addError(ctx, txn, c, int32(line_number), int32(i), fmt.Sprintf("'%s' is not a phone number that we recognize. Ideally it should be of the form '+12223334444'", col))
continue continue
} }
text.EnsureInDB(ctx, txn, *phone) err = text.EnsureInDB(ctx, txn, *phone)
if err != nil {
log.Error().Err(err).Str("phone", col).Msg("ensure in DB failure")
continue
}
setter.ResidentPhoneE164 = omitnull.From(phone.PhoneString()) setter.ResidentPhoneE164 = omitnull.From(phone.PhoneString())
case headerPoolTag: case headerPoolTag:
tags[header_names[i]] = col tags[header_names[i]] = col

View file

@ -23,6 +23,7 @@ import (
"github.com/Gleipnir-Technology/nidus-sync/db" "github.com/Gleipnir-Technology/nidus-sync/db"
"github.com/Gleipnir-Technology/nidus-sync/db/enums" "github.com/Gleipnir-Technology/nidus-sync/db/enums"
"github.com/Gleipnir-Technology/nidus-sync/db/models" "github.com/Gleipnir-Technology/nidus-sync/db/models"
"github.com/Gleipnir-Technology/nidus-sync/lint"
"github.com/aarondl/opt/omit" "github.com/aarondl/opt/omit"
"github.com/aarondl/opt/omitnull" "github.com/aarondl/opt/omitnull"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
@ -67,7 +68,7 @@ func LoadTemplates() error {
if err != nil { if err != nil {
return fmt.Errorf("Failed to start transaction: %w", err) return fmt.Errorf("Failed to start transaction: %w", err)
} }
defer tx.Rollback(ctx) defer lint.LogOnErrCtx(tx.Rollback, ctx, "rollback")
templateByID = make(map[int32]*builtTemplate, 0) templateByID = make(map[int32]*builtTemplate, 0)
for name, p := range all_templates { for name, p := range all_templates {
template_id, err := templateDBID(tx, name, p) template_id, err := templateDBID(tx, name, p)

View file

@ -91,7 +91,7 @@ func ComplianceSend(ctx context.Context, row_id int32) error {
if err != nil { if err != nil {
return fmt.Errorf("start txn: %w", err) return fmt.Errorf("start txn: %w", err)
} }
defer txn.Rollback(nil) defer txn.Rollback(ctx)
mailer, err := models.CommsMailers.Insert(&models.CommsMailerSetter{ mailer, err := models.CommsMailers.Insert(&models.CommsMailerSetter{
AddressID: omit.From(address.ID), AddressID: omit.From(address.ID),
Created: omit.From(time.Now()), Created: omit.From(time.Now()),

View file

@ -4,6 +4,7 @@ import (
"context" "context"
"net/http" "net/http"
"slices" "slices"
"strconv"
"time" "time"
"github.com/Gleipnir-Technology/nidus-sync/config" "github.com/Gleipnir-Technology/nidus-sync/config"
@ -12,7 +13,7 @@ import (
nhttp "github.com/Gleipnir-Technology/nidus-sync/http" nhttp "github.com/Gleipnir-Technology/nidus-sync/http"
"github.com/Gleipnir-Technology/nidus-sync/platform" "github.com/Gleipnir-Technology/nidus-sync/platform"
"github.com/google/uuid" "github.com/google/uuid"
//"github.com/gorilla/mux" "github.com/gorilla/mux"
//"github.com/rs/zerolog/log" //"github.com/rs/zerolog/log"
) )
@ -36,6 +37,7 @@ type communication struct {
Response string `json:"response"` Response string `json:"response"`
Source string `json:"source"` Source string `json:"source"`
Type string `json:"type"` Type string `json:"type"`
URI string `json:"uri"`
} }
func toImageURLs(m map[string][]uuid.UUID, id string) []string { func toImageURLs(m map[string][]uuid.UUID, id string) []string {
@ -49,7 +51,10 @@ func toImageURLs(m map[string][]uuid.UUID, id string) []string {
} }
return urls return urls
} }
func (res *communicationR) List(ctx context.Context, r *http.Request, user platform.User, query QueryParams) ([]*communication, *nhttp.ErrorWithStatus) { func (res *communicationR) Get(ctx context.Context, r *http.Request, user platform.User, query QueryParams) (*communication, *nhttp.ErrorWithStatus) {
return nil, nil
}
func (res *communicationR) List(ctx context.Context, r *http.Request, user platform.User, query QueryParams) ([]communication, *nhttp.ErrorWithStatus) {
comms, err := platform.CommunicationsForOrganization(ctx, int64(user.Organization.ID)) comms, err := platform.CommunicationsForOrganization(ctx, int64(user.Organization.ID))
if err != nil { if err != nil {
return nil, nhttp.NewError("nuisance report query: %w", err) return nil, nhttp.NewError("nuisance report query: %w", err)
@ -68,58 +73,19 @@ func (res *communicationR) List(ctx context.Context, r *http.Request, user platf
for _, pr := range public_reports { for _, pr := range public_reports {
public_report_id_to_report[pr.ID] = pr public_report_id_to_report[pr.ID] = pr
} }
result := make([]*communication, len(comms)) result := make([]communication, len(comms))
for i, comm := range comms { for i, comm := range comms {
source_uri := "unknown"
type_ := "unknown"
if comm.SourceReportID != nil {
public_report, ok := public_report_id_to_report[*comm.SourceReportID] public_report, ok := public_report_id_to_report[*comm.SourceReportID]
if !ok { if !ok {
return nil, nhttp.NewError("lookup report id %d failed", comm.SourceReportID) return nil, nhttp.NewError("lookup report id %d failed", comm.SourceReportID)
} }
source_uri, err = reportURI(res.router, "", public_report.PublicID) c, err := res.hydrateCommunication(*comm, public_report)
if err != nil { if err != nil {
return nil, nhttp.NewError("gen report URI: %w", err) return nil, err
} }
type_ = "publicreport." + public_report.ReportType.String() result[i] = c
} else if comm.SourceEmailLogID != nil {
source_uri, err = emailURI(res.router, *comm.SourceEmailLogID)
if err != nil {
return nil, nhttp.NewError("gen email URI: %w", err)
} }
type_ = "email" _by_created := func(a, b communication) int {
} else if comm.SourceTextLogID != nil {
source_uri, err = textURI(res.router, *comm.SourceTextLogID)
if err != nil {
return nil, nhttp.NewError("gen email URI: %w", err)
}
source_uri = "text"
}
closed_by, err := userURI(res.router, comm.ClosedBy)
if err != nil {
return nil, nhttp.NewError("gen closed_by URI: %w", err)
}
opened_by, err := userURI(res.router, comm.OpenedBy)
if err != nil {
return nil, nhttp.NewError("gen opened_by URI: %w", err)
}
response, err := responseURI(res.router, comm)
if err != nil {
return nil, nhttp.NewError("gen response URI: %w", err)
}
result[i] = &communication{
Closed: comm.Closed,
ClosedBy: closed_by,
Created: comm.Created,
ID: comm.ID,
Opened: comm.Opened,
OpenedBy: opened_by,
Response: response,
Source: source_uri,
Type: type_,
}
}
_by_created := func(a, b *communication) int {
if a.Created.Equal(b.Created) { if a.Created.Equal(b.Created) {
return 0 return 0
} else if a.Created.Before(b.Created) { } else if a.Created.Before(b.Created) {
@ -132,10 +98,93 @@ func (res *communicationR) List(ctx context.Context, r *http.Request, user platf
return result, nil return result, nil
} }
func emailURI(r *router, id int32) (string, error) { type communicationMarkRequest struct{}
return "fake email uri", nil
func (res *communicationR) MarkInvalid(ctx context.Context, r *http.Request, user platform.User, cmr communicationMarkRequest) (communication, *nhttp.ErrorWithStatus) {
return res.markReport(ctx, r, user, platform.CommunicationMarkInvalid)
} }
func responseURI(r *router, comm *modelpublic.Communication) (string, error) { func (res *communicationR) MarkPendingResponse(ctx context.Context, r *http.Request, user platform.User, cmr communicationMarkRequest) (communication, *nhttp.ErrorWithStatus) {
return res.markReport(ctx, r, user, platform.CommunicationMarkPendingResponse)
}
func (res *communicationR) MarkPossibleIssue(ctx context.Context, r *http.Request, user platform.User, cmr communicationMarkRequest) (communication, *nhttp.ErrorWithStatus) {
return res.markReport(ctx, r, user, platform.CommunicationMarkPossibleIssue)
}
func (res *communicationR) MarkPossibleResolved(ctx context.Context, r *http.Request, user platform.User, cmr communicationMarkRequest) (communication, *nhttp.ErrorWithStatus) {
return res.markReport(ctx, r, user, platform.CommunicationMarkPossibleResolved)
}
func (res *communicationR) hydrateCommunication(comm modelpublic.Communication, public_report *modelpublicreport.Report) (communication, *nhttp.ErrorWithStatus) {
var err error
source_uri := "unknown"
type_ := "unknown"
if comm.SourceReportID != nil {
source_uri, err = reportURI(res.router, "", public_report.PublicID)
if err != nil {
return communication{}, nhttp.NewError("gen report URI: %w", err)
}
type_ = "publicreport." + public_report.ReportType.String()
} else if comm.SourceEmailLogID != nil {
source_uri, err = emailURI(*res.router, *comm.SourceEmailLogID)
if err != nil {
return communication{}, nhttp.NewError("gen email URI: %w", err)
}
type_ = "email"
} else if comm.SourceTextLogID != nil {
source_uri, err = textURI(*res.router, *comm.SourceTextLogID)
if err != nil {
return communication{}, nhttp.NewError("gen email URI: %w", err)
}
source_uri = "text"
}
closed_by, err := userURI(res.router, comm.ClosedBy)
if err != nil {
return communication{}, nhttp.NewError("gen closed_by URI: %w", err)
}
opened_by, err := userURI(res.router, comm.OpenedBy)
if err != nil {
return communication{}, nhttp.NewError("gen opened_by URI: %w", err)
}
response, err := responseURI(*res.router, comm)
if err != nil {
return communication{}, nhttp.NewError("gen response URI: %w", err)
}
uri, err := res.router.IDToURI("communication.ByIDGet", int(comm.ID))
if err != nil {
return communication{}, nhttp.NewError("gen comm uri: %w", err)
}
return communication{
Closed: comm.Closed,
ClosedBy: closed_by,
Created: comm.Created,
ID: comm.ID,
Opened: comm.Opened,
OpenedBy: opened_by,
Response: response,
Source: source_uri,
Type: type_,
URI: uri,
}, nil
}
type markFunc = func(context.Context, platform.User, int64) error
func (res *communicationR) markReport(ctx context.Context, r *http.Request, user platform.User, m markFunc) (communication, *nhttp.ErrorWithStatus) {
vars := mux.Vars(r)
report_id_str := vars["id"]
if report_id_str == "" {
return communication{}, nhttp.NewBadRequest("no id provided")
}
report_id, err := strconv.Atoi(report_id_str)
if err != nil {
return communication{}, nhttp.NewBadRequest("can't turn report ID into an int: %w", err)
}
m(ctx, user, int64(report_id))
result, err := platform.CommunicationFromID(ctx, user, int64(report_id))
if result == nil {
return communication{}, nhttp.NewUnauthorized("you are not authorized to modify communication %d", report_id)
}
return res.hydrateCommunication(*result, nil)
}
func responseURI(r router, comm modelpublic.Communication) (string, error) {
if comm.ResponseEmailLogID != nil { if comm.ResponseEmailLogID != nil {
return emailURI(r, *comm.ResponseEmailLogID) return emailURI(r, *comm.ResponseEmailLogID)
} else if comm.ResponseTextLogID != nil { } else if comm.ResponseTextLogID != nil {
@ -144,7 +193,11 @@ func responseURI(r *router, comm *modelpublic.Communication) (string, error) {
return "", nil return "", nil
} }
} }
func textURI(r *router, id int32) (string, error) { func emailURI(r router, id int32) (string, error) {
return "fake email uri", nil
}
func textURI(r router, id int32) (string, error) {
return "fake text uri", nil return "fake text uri", nil
} }
func userURI(r *router, id *int32) (string, error) { func userURI(r *router, id *int32) (string, error) {

View file

@ -39,7 +39,7 @@ type publicReportComplianceForm struct {
HasDog omitnull.Val[bool] `schema:"has_dog" json:"has_dog"` HasDog omitnull.Val[bool] `schema:"has_dog" json:"has_dog"`
Location omit.Val[types.Location] `schema:"location" json:"location"` Location omit.Val[types.Location] `schema:"location" json:"location"`
MailerID omit.Val[string] `schema:"mailer_id" json:"mailer_id"` MailerID omit.Val[string] `schema:"mailer_id" json:"mailer_id"`
PermissionType omit.Val[enums.Permissionaccesstype] `schema:"permission_type" json:"permission_type"` PermissionType omit.Val[enums.PublicreportPermissionaccesstype] `schema:"permission_type" json:"permission_type"`
Reporter omit.Val[types.Contact] `schema:"reporter" json:"reporter"` Reporter omit.Val[types.Contact] `schema:"reporter" json:"reporter"`
ReportPhoneCanSMS omitnull.Val[bool] `schema:"report_phone_can_text" json:"report_phone_can_text"` ReportPhoneCanSMS omitnull.Val[bool] `schema:"report_phone_can_text" json:"report_phone_can_text"`
Submitted omitnull.Val[time.Time] `schema:"submitted" json:"submitted"` Submitted omitnull.Val[time.Time] `schema:"submitted" json:"submitted"`
@ -88,7 +88,7 @@ func (res *complianceR) Create(ctx context.Context, r *http.Request, n publicRep
Comments: omit.From(""), Comments: omit.From(""),
GateCode: omit.From(""), GateCode: omit.From(""),
HasDog: omitnull.FromPtr[bool](nil), HasDog: omitnull.FromPtr[bool](nil),
PermissionType: omit.From(enums.PermissionaccesstypeUnselected), PermissionType: omit.From(enums.PublicreportPermissionaccesstypeUnselected),
//ReportID omit.Val[int32] //ReportID omit.Val[int32]
WantsScheduled: omitnull.FromPtr[bool](nil), WantsScheduled: omitnull.FromPtr[bool](nil),
} }

View file

@ -8,7 +8,7 @@
<div class="card shadow-sm h-100"> <div class="card shadow-sm h-100">
<div class="card-header bg-light pane-header">Actions</div> <div class="card-header bg-light pane-header">Actions</div>
<div class="card-body scroll-pane"> <div class="card-body scroll-pane">
<div v-if="loading" class="loading">Loading...</div> <div v-if="isLoading" class="loading">Loading...</div>
<div v-else> <div v-else>
<div <div
v-if="!selectedCommunication" v-if="!selectedCommunication"
@ -25,22 +25,51 @@
class="actions-panel d-flex flex-column" class="actions-panel d-flex flex-column"
> >
<div class="p-3 flex-grow-1"> <div class="p-3 flex-grow-1">
<!-- Create Signal --> <p class="text-muted mt-1">Send to planning</p>
<div class="d-grid mb-3"> <div class="d-grid mb-3">
<button class="btn btn-success btn-lg" @click="markSignal()"> <ButtonLoading
<i class="bi bi-plus-circle me-2"></i>Mark Signal @click="markPossibleIssue()"
</button> :disabled="!selectedReport"
<small class="text-muted mt-1" icon="bi-plus-circle"
>This report is useful signal</small :loading="isLoading"
> text="Possible Issue"
variant="warning"
/>
</div> </div>
<!-- Mark Invalid -->
<div class="d-grid mb-3"> <div class="d-grid mb-3">
<button class="btn btn-outline-danger" @click="markInvalid()"> <ButtonLoading
<i class="bi bi-x-circle me-2"></i>Mark Invalid @click="markPossibleResolved()"
</button> :disabled="!selectedReport"
<small class="text-muted mt-1">This report isn't useful</small> icon="bi-x-circle"
:loading="isLoading"
text="May Be Resolved"
variant="outline-success"
/>
</div>
<hr />
<div class="d-grid mb-3">
<p class="text-muted mt-1">Resolve immediately</p>
<ButtonLoading
@click="markInvalid()"
:disabled="!selectedReport"
icon="bi-x-circle"
:loading="isLoading"
text="Invalid"
variant="outline-danger"
/>
</div>
<div class="d-grid mb-3">
<ButtonLoading
@click="markPendingResponse()"
:disabled="!selectedReport"
icon="bi-clock"
:loading="isLoading"
text="Pending Response"
variant="secondary"
/>
</div> </div>
<hr /> <hr />
@ -134,14 +163,17 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from "vue"; import { ref } from "vue";
import { Communication, PublicReport, User } from "@/type/api"; import { Communication, PublicReport, User } from "@/type/api";
import ButtonLoading from "@/components/common/ButtonLoading.vue";
import ListCardActivityLog from "@/components/ListCardActivityLog.vue"; import ListCardActivityLog from "@/components/ListCardActivityLog.vue";
interface Emits { interface Emits {
(e: "markSignal"): void;
(e: "markInvalid"): void; (e: "markInvalid"): void;
(e: "markPendingResponse"): void;
(e: "markPossibleIssue"): void;
(e: "markPossibleResolved"): void;
(e: "sendMessage", message: string): void; (e: "sendMessage", message: string): void;
} }
interface Props { interface Props {
loading: boolean; isLoading: boolean;
selectedCommunication: Communication | null; selectedCommunication: Communication | null;
selectedReport: PublicReport | undefined; selectedReport: PublicReport | undefined;
} }
@ -169,8 +201,14 @@ function handleTemplateChange(event: Event) {
function markInvalid() { function markInvalid() {
emit("markInvalid"); emit("markInvalid");
} }
function markSignal() { function markPendingResponse() {
emit("markSignal"); emit("markPendingResponse");
}
function markPossibleResolved() {
emit("markPossibleResolved");
}
function markPossibleIssue() {
emit("markPossibleIssue");
} }
function sendMessage() { function sendMessage() {
emit("sendMessage", messageText.value); emit("sendMessage", messageText.value);

View file

@ -534,6 +534,7 @@ export interface CommunicationDTO {
id: string; id: string;
source: string; source: string;
type: string; type: string;
uri: string;
} }
export class Communication { export class Communication {
constructor( constructor(
@ -541,6 +542,7 @@ export class Communication {
public id: string, public id: string,
public source: string, public source: string,
public type: string, public type: string,
public uri: string,
) {} ) {}
static fromJSON(json: CommunicationDTO): Communication { static fromJSON(json: CommunicationDTO): Communication {
return new Communication( return new Communication(
@ -548,6 +550,7 @@ export class Communication {
json.id, json.id,
json.source, json.source,
json.type, json.type,
json.uri,
); );
} }
} }

View file

@ -33,9 +33,11 @@
</template> </template>
<template #right> <template #right>
<CommunicationColumnAction <CommunicationColumnAction
:loading="storePublicReport.loading || storeCommunication.loading" :isLoading="storePublicReport.loading || storeCommunication.loading"
@markInvalid="markInvalid" @markInvalid="markInvalid"
@markSignal="markSignal" @markPendingResponse="markPendingResponse"
@markPossibleIssue="markPossibleIssue"
@markPossibleResolved="markPossibleResolved"
@sendMessage="sendMessage" @sendMessage="sendMessage"
:selectedCommunication="selectedCommunication" :selectedCommunication="selectedCommunication"
:selectedReport="selectedReport" :selectedReport="selectedReport"
@ -62,6 +64,7 @@ import { computed, onMounted, ref, watch } from "vue";
import { computedAsync } from "@vueuse/core"; import { computedAsync } from "@vueuse/core";
import maplibregl from "maplibre-gl"; import maplibregl from "maplibre-gl";
import { apiClient } from "@/client";
import CommunicationColumnAction from "@/components/CommunicationColumnAction.vue"; import CommunicationColumnAction from "@/components/CommunicationColumnAction.vue";
import CommunicationColumnDetail from "@/components/CommunicationColumnDetail.vue"; import CommunicationColumnDetail from "@/components/CommunicationColumnDetail.vue";
import CommunicationColumnList from "@/components/CommunicationColumnList.vue"; import CommunicationColumnList from "@/components/CommunicationColumnList.vue";
@ -212,58 +215,30 @@ function openImageViewer(index: number) {
} }
async function markInvalid() { async function markInvalid() {
if (selectedCommunication.value == null) { markReport("Invalid", "invalid");
return;
}
console.log("Marking report as invalid:", selectedCommunication.value.id);
const payload = {
reportID: selectedCommunication.value.id,
};
const response = await fetch("/api/publicreport/invalid", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
showNotification(
"Report Marked Invalid",
`Report #${selectedCommunication.value.id} has been marked as invalid`,
);
removeCurrentFromList();
await storeCommunication.fetchAll();
} }
async function markPendingResponse() {
async function markSignal() { markReport("Pending Response", "pending-response");
}
async function markPossibleIssue() {
markReport("Possible Issue", "possible-issue");
}
async function markPossibleResolved() {
markReport("Possibly Resolved", "possible-resolved");
}
async function markReport(title: string, status: string) {
if (selectedCommunication.value == null) { if (selectedCommunication.value == null) {
return; return;
} }
console.log("Marking report as signal:", selectedCommunication.value.id); const url = `${selectedCommunication.value.uri}/${status}`;
try { const result = apiClient.JSONPost(url, {});
const report_id = selectedCommunication.value.id;
const payload = {
reportID: report_id,
};
removeCurrentFromList();
const response = await fetch("api/publicreport/signal", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
if (!response.ok) {
throw new Error("Failed to submit signal");
}
showNotification( showNotification(
"Report Marked Signal", `Report Marked ${title}`,
`Report #${report_id} has been marked as useful signal`, `Report #${selectedCommunication.value.id} has been updated`,
); );
removeCurrentFromList();
await storeCommunication.fetchAll(); await storeCommunication.fetchAll();
} catch (err) {
console.error("Error creating lead:", err);
}
} }
function removeCurrentFromList() { function removeCurrentFromList() {