Update reporter contact on report update
This is as a complicated one because it involves merging contact information in tricky cases. I assume that phone should override email, primarily because setting up phones is more tightly regulated. This may be a terrible assumption. Issue: #13
This commit is contained in:
parent
dcce7cda1c
commit
6175e1a811
5 changed files with 139 additions and 30 deletions
|
|
@ -53,6 +53,24 @@ func ContactEmptyForOrganization(ctx context.Context, txn db.Ex, org_id int64) (
|
||||||
}
|
}
|
||||||
return &row, nil
|
return &row, nil
|
||||||
}
|
}
|
||||||
|
func ContactFromEmail(ctx context.Context, txn db.Ex, email string) (*model.Contact, error) {
|
||||||
|
statement := table.Contact.SELECT(
|
||||||
|
table.Contact.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
table.Contact.INNER_JOIN(
|
||||||
|
table.ContactEmail,
|
||||||
|
table.ContactEmail.ContactID.EQ(table.Contact.ID),
|
||||||
|
),
|
||||||
|
).WHERE(table.ContactEmail.Address.EQ(postgres.String(email)))
|
||||||
|
row, err := db.ExecuteOne[model.Contact](ctx, statement)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, db.ErrNoRows) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("query contact from email '%s': %w", email, err)
|
||||||
|
}
|
||||||
|
return &row, nil
|
||||||
|
}
|
||||||
func ContactFromID(ctx context.Context, txn db.Ex, id int64) (model.Contact, error) {
|
func ContactFromID(ctx context.Context, txn db.Ex, id int64) (model.Contact, error) {
|
||||||
statement := table.Contact.SELECT(
|
statement := table.Contact.SELECT(
|
||||||
table.Contact.AllColumns,
|
table.Contact.AllColumns,
|
||||||
|
|
@ -74,7 +92,24 @@ func ContactsFromIDs(ctx context.Context, txn db.Ex, contact_ids []int64) ([]mod
|
||||||
WHERE(table.Contact.ID.IN(sql_ids...))
|
WHERE(table.Contact.ID.IN(sql_ids...))
|
||||||
return db.ExecuteManyTx[model.Contact](ctx, txn, statement)
|
return db.ExecuteManyTx[model.Contact](ctx, txn, statement)
|
||||||
}
|
}
|
||||||
|
func ContactFromPhone(ctx context.Context, txn db.Ex, e164 string) (*model.Contact, error) {
|
||||||
|
statement := table.Contact.SELECT(
|
||||||
|
table.Contact.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
table.Contact.INNER_JOIN(
|
||||||
|
table.ContactPhone,
|
||||||
|
table.ContactPhone.ContactID.EQ(table.Contact.ID),
|
||||||
|
),
|
||||||
|
).WHERE(table.ContactPhone.E164.EQ(postgres.String(e164)))
|
||||||
|
row, err := db.ExecuteOne[model.Contact](ctx, statement)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, db.ErrNoRows) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("query contact from phone '%s': %w", e164, err)
|
||||||
|
}
|
||||||
|
return &row, nil
|
||||||
|
}
|
||||||
func ContactUpdateName(ctx context.Context, txn db.Ex, id int64, name string) error {
|
func ContactUpdateName(ctx context.Context, txn db.Ex, id int64, name string) error {
|
||||||
statement := table.Contact.UPDATE().
|
statement := table.Contact.UPDATE().
|
||||||
SET(
|
SET(
|
||||||
|
|
|
||||||
|
|
@ -51,3 +51,11 @@ func ContactEmailByContactIDs(ctx context.Context, txn db.Ex, contact_ids []int6
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
func ContactEmailUpdateContactID(ctx context.Context, txn db.Ex, address string, contact_id int64) error {
|
||||||
|
statement := table.ContactEmail.UPDATE().
|
||||||
|
SET(
|
||||||
|
table.ContactEmail.ContactID.SET(postgres.Int(contact_id)),
|
||||||
|
).
|
||||||
|
WHERE(table.ContactEmail.Address.EQ(postgres.String(address)))
|
||||||
|
return db.ExecuteNoneTx(ctx, txn, statement)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func ContactPhoneInsert(ctx context.Context, txn db.Ex, m model.ContactPhone) (model.ContactPhone, error) {
|
func ContactPhoneInsert(ctx context.Context, txn db.Ex, m model.ContactPhone) (model.ContactPhone, error) {
|
||||||
statement := table.ContactPhone.INSERT(table.ContactPhone.MutableColumns).
|
statement := table.ContactPhone.INSERT(table.ContactPhone.AllColumns).
|
||||||
MODEL(m).
|
MODEL(m).
|
||||||
RETURNING(table.ContactPhone.AllColumns)
|
RETURNING(table.ContactPhone.AllColumns)
|
||||||
return db.ExecuteOneTx[model.ContactPhone](ctx, txn, statement)
|
return db.ExecuteOneTx[model.ContactPhone](ctx, txn, statement)
|
||||||
|
|
|
||||||
|
|
@ -126,3 +126,11 @@ func ReportsFromReporterPhone(ctx context.Context, txn db.Ex, destination string
|
||||||
)
|
)
|
||||||
return db.ExecuteManyTx[model.Report](ctx, txn, statement)
|
return db.ExecuteManyTx[model.Report](ctx, txn, statement)
|
||||||
}
|
}
|
||||||
|
func ReportUpdateReporterContactID(ctx context.Context, txn db.Ex, id int64, contact_id int64) error {
|
||||||
|
statement := table.Report.UPDATE().
|
||||||
|
SET(
|
||||||
|
table.Report.ReporterContactID.SET(postgres.Int(contact_id)),
|
||||||
|
).
|
||||||
|
WHERE(table.Report.ID.EQ(postgres.Int(id)))
|
||||||
|
return db.ExecuteNoneTx(ctx, txn, statement)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,43 +79,101 @@ func RegisterSubscriptionPhone(ctx context.Context, txn db.Ex, contact modelcomm
|
||||||
}
|
}
|
||||||
|
|
||||||
func SaveReporter(ctx context.Context, txn db.Ex, report modelpublicreport.Report, name string, email_address string, phone *types.E164, can_sms bool) (contact modelcomms.Contact, err error) {
|
func SaveReporter(ctx context.Context, txn db.Ex, report modelpublicreport.Report, name string, email_address string, phone *types.E164, can_sms bool) (contact modelcomms.Contact, err error) {
|
||||||
contact, err = querycomms.ContactFromID(ctx, txn, int64(report.ReporterContactID))
|
report_contact, err := querycomms.ContactFromID(ctx, txn, int64(report.ReporterContactID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return contact, fmt.Errorf("contact query: %w", err)
|
return contact, fmt.Errorf("contact query: %w", err)
|
||||||
}
|
}
|
||||||
log.Debug().Str("name", name).Str("old name", contact.Name).Int32("id", contact.ID).Msg("contact updated")
|
email_contact, err := querycomms.ContactFromEmail(ctx, txn, email_address)
|
||||||
if name != "" && contact.Name != name {
|
if err != nil {
|
||||||
err = querycomms.ContactUpdateName(ctx, txn, int64(contact.ID), name)
|
return contact, fmt.Errorf("contact query: %w", err)
|
||||||
if err != nil {
|
}
|
||||||
return contact, fmt.Errorf("contact update name: %w", err)
|
phone_contact, err := querycomms.ContactFromPhone(ctx, txn, phone.PhoneString())
|
||||||
|
if err != nil {
|
||||||
|
return contact, fmt.Errorf("contact query: %w", err)
|
||||||
|
}
|
||||||
|
var new_contact_name string
|
||||||
|
new_contact_id := report_contact.ID
|
||||||
|
if phone_contact != nil {
|
||||||
|
// Whether or not the contacts match, we're going to pick the phone contact
|
||||||
|
// as the authoritative one, for no particular reason.
|
||||||
|
new_contact_id = phone_contact.ID
|
||||||
|
if phone_contact.Name != "" {
|
||||||
|
new_contact_name = phone_contact.Name
|
||||||
|
}
|
||||||
|
if email_contact != nil && email_contact.ID != phone_contact.ID {
|
||||||
|
err = querycomms.ContactEmailUpdateContactID(ctx, txn, email_address, int64(phone_contact.ID))
|
||||||
|
if err != nil {
|
||||||
|
return contact, fmt.Errorf("update email contact %d (%d) to %d: %w", email_contact.ID, email_contact.ID, phone_contact.ID, err)
|
||||||
|
}
|
||||||
|
log.Info().Str("address", email_address).Str("e164", phone.PhoneString()).Int32("from-id", email_contact.ID).Int32("to-id", phone_contact.ID).Msg("merged email contact with phone contact")
|
||||||
|
}
|
||||||
|
} else if email_contact != nil {
|
||||||
|
new_contact_id = email_contact.ID
|
||||||
|
if email_contact.Name != "" {
|
||||||
|
new_contact_name = email_contact.Name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if email_address != "" {
|
if name != "" {
|
||||||
e, err := querycomms.ContactEmailInsert(ctx, txn, modelcomms.ContactEmail{
|
new_contact_name = name
|
||||||
Address: email_address,
|
|
||||||
Confirmed: false,
|
|
||||||
ContactID: contact.ID,
|
|
||||||
IsSubscribed: false,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return contact, fmt.Errorf("contact add email: %w", err)
|
|
||||||
}
|
|
||||||
log.Info().Str("address", e.Address).Msg("Created contact email")
|
|
||||||
}
|
}
|
||||||
if phone != nil {
|
if new_contact_id != 0 && new_contact_id != report_contact.ID {
|
||||||
p, err := querycomms.ContactPhoneInsert(ctx, txn, modelcomms.ContactPhone{
|
err = querypublicreport.ReportUpdateReporterContactID(ctx, txn, int64(report.ID), int64(new_contact_id))
|
||||||
CanSms: can_sms,
|
|
||||||
ConfirmedMessageID: nil,
|
|
||||||
ContactID: contact.ID,
|
|
||||||
E164: phone.PhoneString(),
|
|
||||||
IsSubscribed: false,
|
|
||||||
StopMessageID: nil,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return contact, fmt.Errorf("contact add phone: %w", err)
|
return contact, fmt.Errorf("update report %d reporter contact from %d to %d: %w", report.ID, report.ReporterContactID, new_contact_id, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if new_contact_name != "" {
|
||||||
|
err = querycomms.ContactUpdateName(ctx, txn, int64(new_contact_id), new_contact_name)
|
||||||
|
if err != nil {
|
||||||
|
return contact, fmt.Errorf("update contact %d to name %s: %w", new_contact_id, new_contact_name, err)
|
||||||
}
|
}
|
||||||
log.Info().Str("e164", p.E164).Msg("Created contact phone")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Debug().Str("name", name).Str("old name", contact.Name).Int32("id", contact.ID).Msg("contact updated")
|
||||||
|
|
||||||
|
if email_address != "" && email_contact == nil {
|
||||||
|
err = saveReporterEmail(ctx, txn, new_contact_id, email_address)
|
||||||
|
if err != nil {
|
||||||
|
return contact, fmt.Errorf("new contact email for '%s' on %d: %w", email_address, new_contact_id, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if phone != nil && phone_contact == nil {
|
||||||
|
err = saveReporterPhone(ctx, txn, new_contact_id, phone, can_sms)
|
||||||
|
if err != nil {
|
||||||
|
return contact, fmt.Errorf("new contact phone for '%s' on %d: %w", phone.PhoneString(), new_contact_id, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
return contact, nil
|
return contact, nil
|
||||||
}
|
}
|
||||||
|
func saveReporterEmail(ctx context.Context, txn db.Ex, contact_id int32, email_address string) error {
|
||||||
|
e, err := querycomms.ContactEmailInsert(ctx, txn, modelcomms.ContactEmail{
|
||||||
|
Address: email_address,
|
||||||
|
Confirmed: false,
|
||||||
|
ContactID: contact_id,
|
||||||
|
IsSubscribed: false,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("contact add email: %w", err)
|
||||||
|
}
|
||||||
|
log.Info().Str("address", e.Address).Int32("contact_id", contact_id).Msg("Created contact email")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func saveReporterPhone(ctx context.Context, txn db.Ex, contact_id int32, phone *types.E164, can_sms bool) error {
|
||||||
|
if phone == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
p, err := querycomms.ContactPhoneInsert(ctx, txn, modelcomms.ContactPhone{
|
||||||
|
CanSms: can_sms,
|
||||||
|
ConfirmedMessageID: nil,
|
||||||
|
ContactID: contact_id,
|
||||||
|
E164: phone.PhoneString(),
|
||||||
|
IsSubscribed: false,
|
||||||
|
StopMessageID: nil,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("contact add phone: %w", err)
|
||||||
|
}
|
||||||
|
log.Info().Str("e164", p.E164).Int32("contact_id", contact_id).Msg("Created contact phone")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue