Start work on populating context of communication at API layer
Remove communication stub, it's a performance enhancement.
This commit is contained in:
parent
266004624d
commit
e569bb32b7
9 changed files with 331 additions and 119 deletions
|
|
@ -107,6 +107,8 @@ func AddRoutesSync(r *mux.Router) {
|
||||||
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")
|
||||||
|
email := resource.Email(router)
|
||||||
|
r.Handle("/email/{id}", authenticatedHandlerJSON(email.Get)).Methods("GET").Name("email.ByIDGet")
|
||||||
r.Handle("/events", auth.NewEnsureAuth(streamEvents)).Methods("GET")
|
r.Handle("/events", auth.NewEnsureAuth(streamEvents)).Methods("GET")
|
||||||
r.Handle("/image/{uuid}", auth.NewEnsureAuth(apiImagePost)).Methods("POST")
|
r.Handle("/image/{uuid}", auth.NewEnsureAuth(apiImagePost)).Methods("POST")
|
||||||
r.Handle("/image/{uuid}/content", auth.NewEnsureAuth(apiImageContentGet)).Methods("GET")
|
r.Handle("/image/{uuid}/content", auth.NewEnsureAuth(apiImageContentGet)).Methods("GET")
|
||||||
|
|
@ -148,6 +150,8 @@ func AddRoutesSync(r *mux.Router) {
|
||||||
r.Handle("/sudo/email", authenticatedHandlerJSONPost(postSudoEmail)).Methods("POST")
|
r.Handle("/sudo/email", authenticatedHandlerJSONPost(postSudoEmail)).Methods("POST")
|
||||||
r.Handle("/sudo/sms", authenticatedHandlerJSONPost(postSudoSMS)).Methods("POST")
|
r.Handle("/sudo/sms", authenticatedHandlerJSONPost(postSudoSMS)).Methods("POST")
|
||||||
r.Handle("/sudo/sse", authenticatedHandlerJSONPost(postSudoSSE)).Methods("POST")
|
r.Handle("/sudo/sse", authenticatedHandlerJSONPost(postSudoSSE)).Methods("POST")
|
||||||
|
text := resource.Text(router)
|
||||||
|
r.Handle("/text/{id}", authenticatedHandlerJSON(text.Get)).Methods("GET").Name("text.ByIDGet")
|
||||||
r.Handle("/trap-data", auth.NewEnsureAuth(apiTrapData)).Methods("GET")
|
r.Handle("/trap-data", auth.NewEnsureAuth(apiTrapData)).Methods("GET")
|
||||||
r.Handle("/tile/{z}/{y}/{x}", auth.NewEnsureAuth(getTile)).Methods("GET")
|
r.Handle("/tile/{z}/{y}/{x}", auth.NewEnsureAuth(getTile)).Methods("GET")
|
||||||
upload := resource.Upload(r)
|
upload := resource.Upload(r)
|
||||||
|
|
|
||||||
|
|
@ -18,21 +18,6 @@ func CommunicationInsert(ctx context.Context, txn db.Tx, m model.Communication)
|
||||||
RETURNING(table.Communication.AllColumns)
|
RETURNING(table.Communication.AllColumns)
|
||||||
return db.ExecuteOneTx[model.Communication](ctx, txn, statement)
|
return db.ExecuteOneTx[model.Communication](ctx, txn, 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) {
|
|
||||||
statement := table.Communication.SELECT(
|
|
||||||
table.Communication.AllColumns,
|
|
||||||
).FROM(table.Communication).
|
|
||||||
WHERE(table.Communication.OrganizationID.EQ(postgres.Int(org_id))).
|
|
||||||
ORDER_BY(table.Communication.Created.DESC())
|
|
||||||
return db.ExecuteMany[model.Communication](ctx, statement)
|
|
||||||
}
|
|
||||||
func CommunicationSetStatus(ctx context.Context, txn db.Tx, org_id int64, comm_id int64, status model.Communicationstatus) error {
|
func CommunicationSetStatus(ctx context.Context, txn db.Tx, org_id int64, comm_id int64, status model.Communicationstatus) error {
|
||||||
statement := table.Communication.UPDATE().
|
statement := table.Communication.UPDATE().
|
||||||
SET(
|
SET(
|
||||||
|
|
@ -51,3 +36,11 @@ func EmailLogFromID(ctx context.Context, id int64) (model.EmailLog, error) {
|
||||||
WHERE(table.EmailLog.ID.EQ(postgres.Int(id)))
|
WHERE(table.EmailLog.ID.EQ(postgres.Int(id)))
|
||||||
return db.ExecuteOne[model.EmailLog](ctx, statement)
|
return db.ExecuteOne[model.EmailLog](ctx, statement)
|
||||||
}
|
}
|
||||||
|
func EmailLogsFromAddress(ctx context.Context, address string) ([]model.EmailLog, error) {
|
||||||
|
statement := table.EmailLog.SELECT(
|
||||||
|
table.EmailLog.AllColumns,
|
||||||
|
).FROM(table.EmailLog).
|
||||||
|
WHERE(table.EmailLog.Source.EQ(postgres.String(address)).OR(
|
||||||
|
table.EmailLog.Destination.EQ(postgres.String(address))))
|
||||||
|
return db.ExecuteMany[model.EmailLog](ctx, statement)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,3 +16,11 @@ func TextLogFromID(ctx context.Context, id int64) (model.TextLog, error) {
|
||||||
WHERE(table.TextLog.ID.EQ(postgres.Int(id)))
|
WHERE(table.TextLog.ID.EQ(postgres.Int(id)))
|
||||||
return db.ExecuteOne[model.TextLog](ctx, statement)
|
return db.ExecuteOne[model.TextLog](ctx, statement)
|
||||||
}
|
}
|
||||||
|
func TextLogsFromPhoneNumber(ctx context.Context, number string) ([]model.TextLog, error) {
|
||||||
|
statement := table.TextLog.SELECT(
|
||||||
|
table.TextLog.AllColumns,
|
||||||
|
).FROM(table.TextLog).
|
||||||
|
WHERE(table.TextLog.Source.EQ(postgres.String(number)).OR(
|
||||||
|
table.TextLog.Destination.EQ(postgres.String(number))))
|
||||||
|
return db.ExecuteMany[model.TextLog](ctx, statement)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,14 @@ func ReportInsert(ctx context.Context, txn db.Ex, m model.Report) (model.Report,
|
||||||
RETURNING(table.Report.AllColumns)
|
RETURNING(table.Report.AllColumns)
|
||||||
return db.ExecuteOneTx[model.Report](ctx, txn, statement)
|
return db.ExecuteOneTx[model.Report](ctx, txn, statement)
|
||||||
}
|
}
|
||||||
|
func ReportsFromAddressID(ctx context.Context, txn db.Ex, org_id int64, address_id int64) ([]model.Report, error) {
|
||||||
|
statement := table.Report.SELECT(
|
||||||
|
table.Report.AllColumns,
|
||||||
|
).FROM(table.Report).
|
||||||
|
WHERE(table.Report.AddressID.EQ(postgres.Int(address_id)).AND(
|
||||||
|
table.Report.OrganizationID.EQ(postgres.Int(org_id))))
|
||||||
|
return db.ExecuteManyTx[model.Report](ctx, txn, statement)
|
||||||
|
}
|
||||||
func ReportFromID(ctx context.Context, report_id int64) (model.Report, error) {
|
func ReportFromID(ctx context.Context, report_id int64) (model.Report, error) {
|
||||||
statement := table.Report.SELECT(
|
statement := table.Report.SELECT(
|
||||||
table.Report.AllColumns,
|
table.Report.AllColumns,
|
||||||
|
|
@ -87,6 +95,14 @@ func ReportFromPublicIDForOrg(ctx context.Context, txn db.Ex, public_id string,
|
||||||
}
|
}
|
||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
func ReportsFromReporterName(ctx context.Context, txn db.Ex, org_id int64, name string) ([]model.Report, error) {
|
||||||
|
statement := table.Report.SELECT(
|
||||||
|
table.Report.AllColumns,
|
||||||
|
).FROM(table.Report).
|
||||||
|
WHERE(table.Report.ReporterName.EQ(postgres.String(name)).AND(
|
||||||
|
table.Report.OrganizationID.EQ(postgres.Int(org_id))))
|
||||||
|
return db.ExecuteManyTx[model.Report](ctx, txn, statement)
|
||||||
|
}
|
||||||
func ReportsUnreviewedForOrganization(ctx context.Context, txn db.Ex, org_id int64) ([]model.Report, error) {
|
func ReportsUnreviewedForOrganization(ctx context.Context, txn db.Ex, org_id int64) ([]model.Report, error) {
|
||||||
statement := table.Report.SELECT(
|
statement := table.Report.SELECT(
|
||||||
table.Report.AllColumns,
|
table.Report.AllColumns,
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Gleipnir-Technology/nidus-sync/db"
|
"github.com/Gleipnir-Technology/nidus-sync/db"
|
||||||
"github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model"
|
modelpublic "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model"
|
||||||
|
modelpublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model"
|
||||||
querycomms "github.com/Gleipnir-Technology/nidus-sync/db/query/comms"
|
querycomms "github.com/Gleipnir-Technology/nidus-sync/db/query/comms"
|
||||||
querypublic "github.com/Gleipnir-Technology/nidus-sync/db/query/public"
|
querypublic "github.com/Gleipnir-Technology/nidus-sync/db/query/public"
|
||||||
querypublicreport "github.com/Gleipnir-Technology/nidus-sync/db/query/publicreport"
|
querypublicreport "github.com/Gleipnir-Technology/nidus-sync/db/query/publicreport"
|
||||||
|
|
@ -16,12 +17,37 @@ import (
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RelatedRecord struct {
|
type RelatedRecordType int
|
||||||
ID int32
|
|
||||||
Type string
|
const (
|
||||||
|
RelatedRecordTypeUnknown RelatedRecordType = iota
|
||||||
|
RelatedRecordTypeEmail
|
||||||
|
RelatedRecordTypeReportCompliance
|
||||||
|
RelatedRecordTypeReportNuisance
|
||||||
|
RelatedRecordTypeReportWater
|
||||||
|
RelatedRecordTypeText
|
||||||
|
)
|
||||||
|
|
||||||
|
func recordTypeFromReportType(t modelpublicreport.Reporttype) RelatedRecordType {
|
||||||
|
switch t {
|
||||||
|
case modelpublicreport.Reporttype_Compliance:
|
||||||
|
return RelatedRecordTypeReportCompliance
|
||||||
|
case modelpublicreport.Reporttype_Nuisance:
|
||||||
|
return RelatedRecordTypeReportNuisance
|
||||||
|
case modelpublicreport.Reporttype_Water:
|
||||||
|
return RelatedRecordTypeReportWater
|
||||||
|
default:
|
||||||
|
return RelatedRecordTypeUnknown
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func CommunicationRelatedRecords(ctx context.Context, user User, comm *model.Communication) ([]RelatedRecord, error) {
|
type RelatedRecord struct {
|
||||||
|
Created time.Time
|
||||||
|
ID string
|
||||||
|
Type RelatedRecordType
|
||||||
|
}
|
||||||
|
|
||||||
|
func CommunicationRelatedRecords(ctx context.Context, user User, comm *modelpublic.Communication) ([]RelatedRecord, error) {
|
||||||
// Gather associated records
|
// Gather associated records
|
||||||
// * address
|
// * address
|
||||||
// * phone number
|
// * phone number
|
||||||
|
|
@ -33,28 +59,72 @@ func CommunicationRelatedRecords(ctx context.Context, user User, comm *model.Com
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, fmt.Errorf("email log from ID: %w", err)
|
return result, fmt.Errorf("email log from ID: %w", err)
|
||||||
}
|
}
|
||||||
log.Debug().Int32("id", email_log.ID).Send()
|
email_logs, err := querycomms.EmailLogsFromAddress(ctx, email_log.Source)
|
||||||
|
if err != nil {
|
||||||
|
return result, fmt.Errorf("email log from ID: %w", err)
|
||||||
}
|
}
|
||||||
if comm.SourceTextLogID != nil {
|
for _, log := range email_logs {
|
||||||
|
result = append(result, RelatedRecord{
|
||||||
|
Created: log.Created,
|
||||||
|
ID: strconv.Itoa(int(log.ID)),
|
||||||
|
Type: RelatedRecordTypeEmail,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else if comm.SourceTextLogID != nil {
|
||||||
text_log, err := querycomms.TextLogFromID(ctx, int64(*comm.SourceTextLogID))
|
text_log, err := querycomms.TextLogFromID(ctx, int64(*comm.SourceTextLogID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, fmt.Errorf("text log from ID: %w", err)
|
return result, fmt.Errorf("text log from ID: %w", err)
|
||||||
}
|
}
|
||||||
log.Debug().Int32("id", text_log.ID).Send()
|
text_logs, err := querycomms.EmailLogsFromAddress(ctx, text_log.Source)
|
||||||
|
if err != nil {
|
||||||
|
return result, fmt.Errorf("text log from ID: %w", err)
|
||||||
}
|
}
|
||||||
if comm.SourceReportID != nil {
|
for _, log := range text_logs {
|
||||||
|
result = append(result, RelatedRecord{
|
||||||
|
Created: log.Created,
|
||||||
|
ID: strconv.Itoa(int(log.ID)),
|
||||||
|
Type: RelatedRecordTypeText,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else if comm.SourceReportID != nil {
|
||||||
report, err := querypublicreport.ReportFromID(ctx, int64(*comm.SourceReportID))
|
report, err := querypublicreport.ReportFromID(ctx, int64(*comm.SourceReportID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, fmt.Errorf("report from ID: %w", err)
|
return result, fmt.Errorf("report from ID: %w", err)
|
||||||
}
|
}
|
||||||
log.Debug().Int32("id", report.ID).Send()
|
if report.ReporterName != "" {
|
||||||
|
reports_by_name, err := querypublicreport.ReportsFromReporterName(ctx, db.PGInstance.PGXPool, int64(user.Organization.ID), report.ReporterName)
|
||||||
|
if err != nil {
|
||||||
|
return result, fmt.Errorf("reports from reporter name '%s': %w", report.ReporterName, err)
|
||||||
|
}
|
||||||
|
for _, r := range reports_by_name {
|
||||||
|
record_type := recordTypeFromReportType(r.ReportType)
|
||||||
|
result = append(result, RelatedRecord{
|
||||||
|
Created: r.Created,
|
||||||
|
ID: r.PublicID,
|
||||||
|
Type: record_type,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if report.AddressID != nil {
|
||||||
|
reports_by_address, err := querypublicreport.ReportsFromAddressID(ctx, db.PGInstance.PGXPool, int64(user.Organization.ID), int64(*report.AddressID))
|
||||||
|
if err != nil {
|
||||||
|
return result, fmt.Errorf("reports from reporter name '%s': %w", report.ReporterName, err)
|
||||||
|
}
|
||||||
|
for _, r := range reports_by_address {
|
||||||
|
record_type := recordTypeFromReportType(r.ReportType)
|
||||||
|
result = append(result, RelatedRecord{
|
||||||
|
ID: r.PublicID,
|
||||||
|
Type: record_type,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
func CommunicationsForOrganization(ctx context.Context, org_id int64) ([]model.Communication, error) {
|
func CommunicationsForOrganization(ctx context.Context, org_id int64) ([]modelpublic.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) {
|
func CommunicationFromID(ctx context.Context, user User, comm_id int64) (*modelpublic.Communication, error) {
|
||||||
comm, err := querypublic.CommunicationFromID(ctx, comm_id)
|
comm, err := querypublic.CommunicationFromID(ctx, comm_id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -65,19 +135,19 @@ func CommunicationFromID(ctx context.Context, user User, comm_id int64) (*model.
|
||||||
return &comm, nil
|
return &comm, nil
|
||||||
}
|
}
|
||||||
func CommunicationMarkInvalid(ctx context.Context, user User, comm_id int32) error {
|
func CommunicationMarkInvalid(ctx context.Context, user User, comm_id int32) error {
|
||||||
return communicationMark(ctx, user, comm_id, model.Communicationstatus_Invalid, model.Communicationlogentry_StatusInvalidated)
|
return communicationMark(ctx, user, comm_id, modelpublic.Communicationstatus_Invalid, modelpublic.Communicationlogentry_StatusInvalidated)
|
||||||
}
|
}
|
||||||
func CommunicationMarkPendingResponse(ctx context.Context, user User, comm_id int32) error {
|
func CommunicationMarkPendingResponse(ctx context.Context, user User, comm_id int32) error {
|
||||||
return communicationMark(ctx, user, comm_id, model.Communicationstatus_Pending, model.Communicationlogentry_StatusPending)
|
return communicationMark(ctx, user, comm_id, modelpublic.Communicationstatus_Pending, modelpublic.Communicationlogentry_StatusPending)
|
||||||
}
|
}
|
||||||
func CommunicationMarkPossibleIssue(ctx context.Context, user User, comm_id int32) error {
|
func CommunicationMarkPossibleIssue(ctx context.Context, user User, comm_id int32) error {
|
||||||
return communicationMark(ctx, user, comm_id, model.Communicationstatus_PossibleIssue, model.Communicationlogentry_StatusPossibleIssue)
|
return communicationMark(ctx, user, comm_id, modelpublic.Communicationstatus_PossibleIssue, modelpublic.Communicationlogentry_StatusPossibleIssue)
|
||||||
}
|
}
|
||||||
func CommunicationMarkPossibleResolved(ctx context.Context, user User, comm_id int32) error {
|
func CommunicationMarkPossibleResolved(ctx context.Context, user User, comm_id int32) error {
|
||||||
return communicationMark(ctx, user, comm_id, model.Communicationstatus_PossibleResolved, model.Communicationlogentry_StatusPossibleResolved)
|
return communicationMark(ctx, user, comm_id, modelpublic.Communicationstatus_PossibleResolved, modelpublic.Communicationlogentry_StatusPossibleResolved)
|
||||||
}
|
}
|
||||||
|
|
||||||
func communicationMark(ctx context.Context, user User, comm_id int32, status model.Communicationstatus, log_type model.Communicationlogentry) error {
|
func communicationMark(ctx context.Context, user User, comm_id int32, status modelpublic.Communicationstatus, log_type modelpublic.Communicationlogentry) error {
|
||||||
txn, err := db.BeginTxn(ctx)
|
txn, err := db.BeginTxn(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("begin txn: %w", err)
|
return fmt.Errorf("begin txn: %w", err)
|
||||||
|
|
@ -88,7 +158,7 @@ func communicationMark(ctx context.Context, user User, comm_id int32, status mod
|
||||||
return fmt.Errorf("mark: %w", err)
|
return fmt.Errorf("mark: %w", err)
|
||||||
}
|
}
|
||||||
user_id := int32(user.ID)
|
user_id := int32(user.ID)
|
||||||
log_entry := model.CommunicationLogEntry{
|
log_entry := modelpublic.CommunicationLogEntry{
|
||||||
CommunicationID: comm_id,
|
CommunicationID: comm_id,
|
||||||
Created: time.Now(),
|
Created: time.Now(),
|
||||||
Type: log_type,
|
Type: log_type,
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package resource
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -10,8 +11,7 @@ import (
|
||||||
modelpublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model"
|
modelpublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model"
|
||||||
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/gorilla/mux"
|
"github.com/rs/zerolog/log"
|
||||||
//"github.com/rs/zerolog/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type communicationR struct {
|
type communicationR struct {
|
||||||
|
|
@ -24,45 +24,58 @@ func Communication(r *router) *communicationR {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type communicationLogType string
|
||||||
|
type communicationType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
communicationTypeUnknown communicationType = "unknown"
|
||||||
|
communicationTypeReportCompliance = "publicreport.compliance"
|
||||||
|
communicationTypeReportNuisance = "publicreport.nuisance"
|
||||||
|
communicationTypeReportWater = "publicreport.water"
|
||||||
|
)
|
||||||
|
|
||||||
type communicationLog struct {
|
type communicationLog struct {
|
||||||
Created time.Time `json:"created"`
|
Created time.Time `json:"created"`
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Type string `json:"type"`
|
Type communicationLogType `json:"type"`
|
||||||
User string `json:"user"`
|
User string `json:"user"`
|
||||||
}
|
}
|
||||||
type communication struct {
|
type communication struct {
|
||||||
Context []resourceStub `json:"context"`
|
|
||||||
Created time.Time `json:"created"`
|
Created time.Time `json:"created"`
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Log []communicationLog `json:"log"`
|
Log []communicationLog `json:"log"`
|
||||||
|
Related []resourceStub `json:"related"`
|
||||||
Response string `json:"response"`
|
Response string `json:"response"`
|
||||||
Source string `json:"source"`
|
Source string `json:"source"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
Type string `json:"type"`
|
Type communicationType `json:"type"`
|
||||||
URI string `json:"uri"`
|
|
||||||
}
|
|
||||||
type communicationStub struct {
|
|
||||||
Created time.Time `json:"created"`
|
|
||||||
ID string `json:"id"`
|
|
||||||
Source string `json:"source"`
|
|
||||||
Status string `json:"status"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
URI string `json:"uri"`
|
URI string `json:"uri"`
|
||||||
}
|
}
|
||||||
|
type resourceType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
resourceTypeUnknown resourceType = "unknown"
|
||||||
|
resourceTypeEmail = "email"
|
||||||
|
resourceTypeReportCompliance = "publicreport.compliance"
|
||||||
|
resourceTypeReportNuisance = "publicreport.nuisance"
|
||||||
|
resourceTypeReportWater = "publicreport.water"
|
||||||
|
resourceTypeText = "text"
|
||||||
|
)
|
||||||
|
|
||||||
type resourceStub struct {
|
type resourceStub struct {
|
||||||
Created time.Time `json:"created"`
|
Created time.Time `json:"created"`
|
||||||
Type string `json:"type"`
|
Type resourceType `json:"type"`
|
||||||
URI string `json:"uri"`
|
URI string `json:"uri"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (res *communicationR) Get(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) {
|
||||||
comm_id, error_with_status := communicationIDFromMux(r)
|
comm_id, error_with_status := res.router.IDFromMux(r)
|
||||||
if error_with_status != nil {
|
if error_with_status != nil {
|
||||||
return communication{}, error_with_status
|
return communication{}, error_with_status
|
||||||
}
|
}
|
||||||
return res.hydratedCommunicationFromID(ctx, user, int32(comm_id))
|
return res.hydratedCommunicationFromID(ctx, user, int32(comm_id))
|
||||||
}
|
}
|
||||||
func (res *communicationR) List(ctx context.Context, r *http.Request, user platform.User, query QueryParams) ([]communicationStub, *nhttp.ErrorWithStatus) {
|
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)
|
||||||
|
|
@ -81,13 +94,17 @@ 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([]communicationStub, len(comms))
|
result := make([]communication, len(comms))
|
||||||
for i, comm := range comms {
|
for i, comm := range comms {
|
||||||
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)
|
||||||
}
|
}
|
||||||
c, e := res.hydrateCommunicationStub(comm, &public_report)
|
related_records, err := platform.CommunicationRelatedRecords(ctx, user, &comm)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nhttp.NewError("related records: %w", err)
|
||||||
|
}
|
||||||
|
c, e := res.hydrateCommunication(comm, related_records, &public_report)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, e
|
return nil, e
|
||||||
}
|
}
|
||||||
|
|
@ -110,55 +127,85 @@ func (res *communicationR) MarkPossibleIssue(ctx context.Context, r *http.Reques
|
||||||
func (res *communicationR) MarkPossibleResolved(ctx context.Context, r *http.Request, user platform.User, cmr communicationMarkRequest) (communication, *nhttp.ErrorWithStatus) {
|
func (res *communicationR) MarkPossibleResolved(ctx context.Context, r *http.Request, user platform.User, cmr communicationMarkRequest) (communication, *nhttp.ErrorWithStatus) {
|
||||||
return res.markCommunication(ctx, r, user, "possible-resolved", platform.CommunicationMarkPossibleResolved)
|
return res.markCommunication(ctx, r, user, "possible-resolved", platform.CommunicationMarkPossibleResolved)
|
||||||
}
|
}
|
||||||
func (res *communicationR) hydrateCommunication(comm modelpublic.Communication, public_report *modelpublicreport.Report) (communication, *nhttp.ErrorWithStatus) {
|
func (res *communicationR) hydrateCommunication(comm modelpublic.Communication, related_records []platform.RelatedRecord, public_report *modelpublicreport.Report) (communication, *nhttp.ErrorWithStatus) {
|
||||||
stub, e := res.hydrateCommunicationStub(comm, public_report)
|
var err error
|
||||||
if e != nil {
|
source_uri := "unknown"
|
||||||
return communication{}, e
|
type_ := communicationTypeUnknown
|
||||||
|
if comm.SourceReportID != nil && public_report != nil {
|
||||||
|
source_uri, err = reportURI(res.router, "", public_report.PublicID)
|
||||||
|
if err != nil {
|
||||||
|
return communication{}, nhttp.NewError("gen report URI: %w", err)
|
||||||
|
}
|
||||||
|
switch public_report.ReportType {
|
||||||
|
case modelpublicreport.Reporttype_Compliance:
|
||||||
|
type_ = communicationTypeReportCompliance
|
||||||
|
case modelpublicreport.Reporttype_Nuisance:
|
||||||
|
type_ = communicationTypeReportNuisance
|
||||||
|
case modelpublicreport.Reporttype_Water:
|
||||||
|
type_ = communicationTypeReportWater
|
||||||
|
default:
|
||||||
|
type_ = communicationTypeUnknown
|
||||||
|
}
|
||||||
|
} 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"
|
||||||
|
}
|
||||||
|
uri, err := res.router.IDToURI("communication.ByIDGet", int(comm.ID))
|
||||||
|
if err != nil {
|
||||||
|
return communication{}, nhttp.NewError("gen comm uri: %w", err)
|
||||||
|
}
|
||||||
|
related := make([]resourceStub, len(related_records))
|
||||||
|
for i, rr := range related_records {
|
||||||
|
var uri string
|
||||||
|
var r_type resourceType
|
||||||
|
switch rr.Type {
|
||||||
|
case platform.RelatedRecordTypeEmail:
|
||||||
|
r_type = resourceTypeEmail
|
||||||
|
uri, err = res.router.IDStrToURI("email.GetByID", rr.ID)
|
||||||
|
case platform.RelatedRecordTypeReportCompliance:
|
||||||
|
r_type = resourceTypeReportCompliance
|
||||||
|
uri, err = res.router.IDStrToURI("publicreport.compliance.GetByID", rr.ID)
|
||||||
|
case platform.RelatedRecordTypeReportNuisance:
|
||||||
|
r_type = resourceTypeReportNuisance
|
||||||
|
uri, err = res.router.IDStrToURI("publicreport.nuisance.GetByID", rr.ID)
|
||||||
|
case platform.RelatedRecordTypeReportWater:
|
||||||
|
r_type = resourceTypeReportWater
|
||||||
|
uri, err = res.router.IDStrToURI("publicreport.water.GetByID", rr.ID)
|
||||||
|
case platform.RelatedRecordTypeText:
|
||||||
|
r_type = resourceTypeText
|
||||||
|
uri, err = res.router.IDStrToURI("text.GetByID", rr.ID)
|
||||||
|
default:
|
||||||
|
r_type = resourceTypeUnknown
|
||||||
|
err = fmt.Errorf("unrecognized related record type '%s'", rr.Type)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return communication{}, nhttp.NewError("related record hydration: %w", err)
|
||||||
|
}
|
||||||
|
related[i] = resourceStub{
|
||||||
|
Created: rr.Created,
|
||||||
|
Type: r_type,
|
||||||
|
URI: uri,
|
||||||
|
}
|
||||||
|
log.Debug().Str("created", rr.Created.String()).Str("id", rr.ID).Str("uri", uri).Msg("related record")
|
||||||
}
|
}
|
||||||
response, err := responseURI(*res.router, comm)
|
response, err := responseURI(*res.router, comm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return communication{}, nhttp.NewError("gen response URI: %w", err)
|
return communication{}, nhttp.NewError("gen response URI: %w", err)
|
||||||
}
|
}
|
||||||
return communication{
|
return communication{
|
||||||
Created: stub.Created,
|
|
||||||
ID: stub.ID,
|
|
||||||
Response: response,
|
|
||||||
Source: stub.Source,
|
|
||||||
Status: stub.Status,
|
|
||||||
Type: stub.Type,
|
|
||||||
URI: stub.URI,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
func (res *communicationR) hydrateCommunicationStub(comm modelpublic.Communication, public_report *modelpublicreport.Report) (communicationStub, *nhttp.ErrorWithStatus) {
|
|
||||||
var err error
|
|
||||||
source_uri := "unknown"
|
|
||||||
type_ := "unknown"
|
|
||||||
if comm.SourceReportID != nil && public_report != nil {
|
|
||||||
source_uri, err = reportURI(res.router, "", public_report.PublicID)
|
|
||||||
if err != nil {
|
|
||||||
return communicationStub{}, 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 communicationStub{}, 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 communicationStub{}, nhttp.NewError("gen email URI: %w", err)
|
|
||||||
}
|
|
||||||
source_uri = "text"
|
|
||||||
}
|
|
||||||
uri, err := res.router.IDToURI("communication.ByIDGet", int(comm.ID))
|
|
||||||
if err != nil {
|
|
||||||
return communicationStub{}, nhttp.NewError("gen comm uri: %w", err)
|
|
||||||
}
|
|
||||||
return communicationStub{
|
|
||||||
Created: comm.Created,
|
Created: comm.Created,
|
||||||
ID: strconv.Itoa(int(comm.ID)),
|
ID: strconv.Itoa(int(comm.ID)),
|
||||||
|
Related: related,
|
||||||
|
Response: response,
|
||||||
Source: source_uri,
|
Source: source_uri,
|
||||||
Status: comm.Status.String(),
|
Status: comm.Status.String(),
|
||||||
Type: type_,
|
Type: type_,
|
||||||
|
|
@ -184,14 +231,18 @@ func (res *communicationR) hydratedCommunicationFromID(ctx context.Context, user
|
||||||
}
|
}
|
||||||
public_report = public_reports[0]
|
public_report = public_reports[0]
|
||||||
}
|
}
|
||||||
|
related_records, err := platform.CommunicationRelatedRecords(ctx, user, comm)
|
||||||
|
if err != nil {
|
||||||
|
return communication{}, nhttp.NewError("related records: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
return res.hydrateCommunication(*comm, &public_report)
|
return res.hydrateCommunication(*comm, related_records, &public_report)
|
||||||
}
|
}
|
||||||
|
|
||||||
type markFunc = func(context.Context, platform.User, int32) error
|
type markFunc = func(context.Context, platform.User, int32) error
|
||||||
|
|
||||||
func (res *communicationR) markCommunication(ctx context.Context, r *http.Request, user platform.User, status string, m markFunc) (communication, *nhttp.ErrorWithStatus) {
|
func (res *communicationR) markCommunication(ctx context.Context, r *http.Request, user platform.User, status string, m markFunc) (communication, *nhttp.ErrorWithStatus) {
|
||||||
comm_id, err_with_status := communicationIDFromMux(r)
|
comm_id, err_with_status := res.router.IDFromMux(r)
|
||||||
if err_with_status != nil {
|
if err_with_status != nil {
|
||||||
return communication{}, err_with_status
|
return communication{}, err_with_status
|
||||||
}
|
}
|
||||||
|
|
@ -201,18 +252,6 @@ func (res *communicationR) markCommunication(ctx context.Context, r *http.Reques
|
||||||
}
|
}
|
||||||
return res.hydratedCommunicationFromID(ctx, user, int32(comm_id))
|
return res.hydratedCommunicationFromID(ctx, user, int32(comm_id))
|
||||||
}
|
}
|
||||||
func communicationIDFromMux(r *http.Request) (int, *nhttp.ErrorWithStatus) {
|
|
||||||
vars := mux.Vars(r)
|
|
||||||
comm_id_str := vars["id"]
|
|
||||||
if comm_id_str == "" {
|
|
||||||
return 0, nhttp.NewBadRequest("no id provided")
|
|
||||||
}
|
|
||||||
comm_id, err := strconv.Atoi(comm_id_str)
|
|
||||||
if err != nil {
|
|
||||||
return 0, nhttp.NewBadRequest("can't turn report ID into an int: %w", err)
|
|
||||||
}
|
|
||||||
return comm_id, nil
|
|
||||||
}
|
|
||||||
func responseURI(r router, comm modelpublic.Communication) (string, error) {
|
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)
|
||||||
|
|
@ -229,4 +268,3 @@ func emailURI(r router, id int32) (string, error) {
|
||||||
func textURI(r router, id int32) (string, error) {
|
func textURI(r router, id int32) (string, error) {
|
||||||
return "fake text uri", nil
|
return "fake text uri", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
35
resource/email.go
Normal file
35
resource/email.go
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
package resource
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
//modelpublic "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model"
|
||||||
|
//modelpublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model"
|
||||||
|
nhttp "github.com/Gleipnir-Technology/nidus-sync/http"
|
||||||
|
"github.com/Gleipnir-Technology/nidus-sync/platform"
|
||||||
|
//"github.com/gorilla/mux"
|
||||||
|
//"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type emailR struct {
|
||||||
|
router *router
|
||||||
|
}
|
||||||
|
|
||||||
|
func Email(r *router) *emailR {
|
||||||
|
return &emailR{
|
||||||
|
router: r,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type email struct {
|
||||||
|
ID int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (res *emailR) Get(ctx context.Context, r *http.Request, user platform.User, query QueryParams) (email, *nhttp.ErrorWithStatus) {
|
||||||
|
email_id, error_with_status := res.router.IDFromMux(r)
|
||||||
|
if error_with_status != nil {
|
||||||
|
return email{}, error_with_status
|
||||||
|
}
|
||||||
|
return email{ID: email_id}, nil
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
nhttp "github.com/Gleipnir-Technology/nidus-sync/http"
|
||||||
"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"
|
||||||
|
|
@ -19,6 +20,18 @@ func NewRouter(r *mux.Router) *router {
|
||||||
router: r,
|
router: r,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func (r *router) IDFromMux(req *http.Request) (int, *nhttp.ErrorWithStatus) {
|
||||||
|
vars := mux.Vars(req)
|
||||||
|
comm_id_str := vars["id"]
|
||||||
|
if comm_id_str == "" {
|
||||||
|
return 0, nhttp.NewBadRequest("no id provided")
|
||||||
|
}
|
||||||
|
comm_id, err := strconv.Atoi(comm_id_str)
|
||||||
|
if err != nil {
|
||||||
|
return 0, nhttp.NewBadRequest("can't turn report ID into an int: %w", err)
|
||||||
|
}
|
||||||
|
return comm_id, nil
|
||||||
|
}
|
||||||
func (r *router) IDFromURI(route string, uri string) (*int, error) {
|
func (r *router) IDFromURI(route string, uri string) (*int, error) {
|
||||||
var match mux.RouteMatch
|
var match mux.RouteMatch
|
||||||
req, _ := http.NewRequest("GET", uri, nil)
|
req, _ := http.NewRequest("GET", uri, nil)
|
||||||
|
|
|
||||||
35
resource/text.go
Normal file
35
resource/text.go
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
package resource
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
//modelpublic "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/public/model"
|
||||||
|
//modelpublicreport "github.com/Gleipnir-Technology/nidus-sync/db/gen/nidus-sync/publicreport/model"
|
||||||
|
nhttp "github.com/Gleipnir-Technology/nidus-sync/http"
|
||||||
|
"github.com/Gleipnir-Technology/nidus-sync/platform"
|
||||||
|
//"github.com/gorilla/mux"
|
||||||
|
//"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type textR struct {
|
||||||
|
router *router
|
||||||
|
}
|
||||||
|
|
||||||
|
func Text(r *router) *textR {
|
||||||
|
return &textR{
|
||||||
|
router: r,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type textResource struct {
|
||||||
|
ID int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (res *textR) Get(ctx context.Context, r *http.Request, user platform.User, query QueryParams) (textResource, *nhttp.ErrorWithStatus) {
|
||||||
|
text_id, error_with_status := res.router.IDFromMux(r)
|
||||||
|
if error_with_status != nil {
|
||||||
|
return textResource{}, error_with_status
|
||||||
|
}
|
||||||
|
return textResource{ID: text_id}, nil
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue