Some checks failed
CI / build-and-test (push) Failing after -31m12s
All internal entity lookups now use bigserial primary keys (int64) while GUIDs are retained for external/public identification. Updated store functions (TouchProject, UpdateThoughtMetadata, AddThoughtAttachment) to query by id instead of guid, added GetThoughtByID, changed semanticSearch and all tool helpers to use *int64 project IDs, and updated retry/backfill workers to use int64 thought IDs throughout.
541 lines
14 KiB
Go
541 lines
14 KiB
Go
package store
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"time"
|
|
|
|
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
|
|
ext "git.warky.dev/wdevs/amcs/internal/types"
|
|
)
|
|
|
|
func projectFromModel(m generatedmodels.ModelPublicProjects) ext.Project {
|
|
return ext.Project{
|
|
ID: m.GUID.UUID(),
|
|
NumericID: m.ID.Int64(),
|
|
Name: m.Name.String(),
|
|
Description: m.Description.String(),
|
|
CreatedAt: m.CreatedAt.Time(),
|
|
LastActiveAt: m.LastActiveAt.Time(),
|
|
}
|
|
}
|
|
|
|
func thoughtFromModel(m generatedmodels.ModelPublicThoughts) (ext.Thought, error) {
|
|
var metadata ext.ThoughtMetadata
|
|
if len(m.Metadata) > 0 {
|
|
if err := json.Unmarshal(m.Metadata, &metadata); err != nil {
|
|
return ext.Thought{}, fmt.Errorf("decode thought metadata: %w", err)
|
|
}
|
|
}
|
|
|
|
var projectID *int64
|
|
if m.ProjectID.Valid {
|
|
id := m.ProjectID.Int64()
|
|
projectID = &id
|
|
}
|
|
|
|
var archivedAt *time.Time
|
|
if m.ArchivedAt.Valid {
|
|
t := m.ArchivedAt.Time()
|
|
archivedAt = &t
|
|
}
|
|
|
|
return ext.Thought{
|
|
ID: m.ID.Int64(),
|
|
GUID: m.GUID.UUID(),
|
|
Content: m.Content.String(),
|
|
Metadata: metadata,
|
|
ProjectID: projectID,
|
|
ArchivedAt: archivedAt,
|
|
CreatedAt: m.CreatedAt.Time(),
|
|
UpdatedAt: m.UpdatedAt.Time(),
|
|
}, nil
|
|
}
|
|
|
|
func storedFileFromModel(m generatedmodels.ModelPublicStoredFiles) ext.StoredFile {
|
|
var thoughtID *int64
|
|
if m.ThoughtID.Valid {
|
|
id := m.ThoughtID.Int64()
|
|
thoughtID = &id
|
|
}
|
|
|
|
var projectID *int64
|
|
if m.ProjectID.Valid {
|
|
id := m.ProjectID.Int64()
|
|
projectID = &id
|
|
}
|
|
|
|
return ext.StoredFile{
|
|
ID: m.ID.Int64(),
|
|
GUID: m.GUID.UUID(),
|
|
ThoughtID: thoughtID,
|
|
ProjectID: projectID,
|
|
Name: m.Name.String(),
|
|
MediaType: m.MediaType.String(),
|
|
Kind: m.Kind.String(),
|
|
Encoding: m.Encoding.String(),
|
|
SizeBytes: m.SizeBytes,
|
|
SHA256: m.Sha256.String(),
|
|
Content: m.Content,
|
|
CreatedAt: m.CreatedAt.Time(),
|
|
UpdatedAt: m.UpdatedAt.Time(),
|
|
}
|
|
}
|
|
|
|
// func maintenanceTaskFromModel(m generatedmodels.ModelPublicMaintenanceTasks) ext.MaintenanceTask {
|
|
// var frequencyDays *int
|
|
// if m.FrequencyDays.Valid {
|
|
// n := int(m.FrequencyDays.Int64())
|
|
// frequencyDays = &n
|
|
// }
|
|
|
|
// var lastCompleted *time.Time
|
|
// if m.LastCompleted.Valid {
|
|
// t := m.LastCompleted.Time()
|
|
// lastCompleted = &t
|
|
// }
|
|
|
|
// var nextDue *time.Time
|
|
// if m.NextDue.Valid {
|
|
// t := m.NextDue.Time()
|
|
// nextDue = &t
|
|
// }
|
|
|
|
// return ext.MaintenanceTask{
|
|
// ID: m.ID.UUID(),
|
|
// Name: m.Name.String(),
|
|
// Category: m.Category.String(),
|
|
// FrequencyDays: frequencyDays,
|
|
// LastCompleted: lastCompleted,
|
|
// NextDue: nextDue,
|
|
// Priority: m.Priority.String(),
|
|
// Notes: m.Notes.String(),
|
|
// CreatedAt: m.CreatedAt.Time(),
|
|
// UpdatedAt: m.UpdatedAt.Time(),
|
|
// }
|
|
// }
|
|
|
|
// func maintenanceLogFromModel(m generatedmodels.ModelPublicMaintenanceLogs) ext.MaintenanceLog {
|
|
// var cost *float64
|
|
// if m.Cost.Valid {
|
|
// v := m.Cost.Float64()
|
|
// cost = &v
|
|
// }
|
|
|
|
// return ext.MaintenanceLog{
|
|
// ID: m.ID.UUID(),
|
|
// TaskID: m.TaskID.UUID(),
|
|
// CompletedAt: m.CompletedAt.Time(),
|
|
// PerformedBy: m.PerformedBy.String(),
|
|
// Cost: cost,
|
|
// Notes: m.Notes.String(),
|
|
// NextAction: m.NextAction.String(),
|
|
// }
|
|
// }
|
|
|
|
// func householdItemFromModel(m generatedmodels.ModelPublicHouseholdItems) ext.HouseholdItem {
|
|
// details := map[string]any{}
|
|
// if len(m.Details) > 0 {
|
|
// if err := json.Unmarshal(m.Details, &details); err != nil {
|
|
// details = map[string]any{}
|
|
// }
|
|
// }
|
|
|
|
// return ext.HouseholdItem{
|
|
// ID: m.ID.UUID(),
|
|
// Name: m.Name.String(),
|
|
// Category: m.Category.String(),
|
|
// Location: m.Location.String(),
|
|
// Details: details,
|
|
// Notes: m.Notes.String(),
|
|
// CreatedAt: m.CreatedAt.Time(),
|
|
// UpdatedAt: m.UpdatedAt.Time(),
|
|
// }
|
|
// }
|
|
|
|
// func householdVendorFromModel(m generatedmodels.ModelPublicHouseholdVendors) ext.HouseholdVendor {
|
|
// var rating *int
|
|
// if m.Rating.Valid {
|
|
// v := int(m.Rating.Int64())
|
|
// rating = &v
|
|
// }
|
|
|
|
// var lastUsed *time.Time
|
|
// if m.LastUsed.Valid {
|
|
// t := m.LastUsed.Time()
|
|
// lastUsed = &t
|
|
// }
|
|
|
|
// return ext.HouseholdVendor{
|
|
// ID: m.ID.UUID(),
|
|
// Name: m.Name.String(),
|
|
// ServiceType: m.ServiceType.String(),
|
|
// Phone: m.Phone.String(),
|
|
// Email: m.Email.String(),
|
|
// Website: m.Website.String(),
|
|
// Notes: m.Notes.String(),
|
|
// Rating: rating,
|
|
// LastUsed: lastUsed,
|
|
// CreatedAt: m.CreatedAt.Time(),
|
|
// }
|
|
// }
|
|
|
|
// func familyMemberFromModel(m generatedmodels.ModelPublicFamilyMembers) ext.FamilyMember {
|
|
// var birthDate *time.Time
|
|
// if m.BirthDate.Valid {
|
|
// t := m.BirthDate.Time()
|
|
// birthDate = &t
|
|
// }
|
|
|
|
// return ext.FamilyMember{
|
|
// ID: m.ID.UUID(),
|
|
// Name: m.Name.String(),
|
|
// Relationship: m.Relationship.String(),
|
|
// BirthDate: birthDate,
|
|
// Notes: m.Notes.String(),
|
|
// CreatedAt: m.CreatedAt.Time(),
|
|
// }
|
|
// }
|
|
|
|
// func activityFromModel(m generatedmodels.ModelPublicActivities, memberName string) ext.Activity {
|
|
// var familyMemberID *uuid.UUID
|
|
// if m.FamilyMemberID.Valid {
|
|
// id := m.FamilyMemberID.UUID()
|
|
// familyMemberID = &id
|
|
// }
|
|
|
|
// var startDate *time.Time
|
|
// if m.StartDate.Valid {
|
|
// t := m.StartDate.Time()
|
|
// startDate = &t
|
|
// }
|
|
|
|
// var endDate *time.Time
|
|
// if m.EndDate.Valid {
|
|
// t := m.EndDate.Time()
|
|
// endDate = &t
|
|
// }
|
|
|
|
// return ext.Activity{
|
|
// ID: m.ID.UUID(),
|
|
// FamilyMemberID: familyMemberID,
|
|
// MemberName: memberName,
|
|
// Title: m.Title.String(),
|
|
// ActivityType: m.ActivityType.String(),
|
|
// DayOfWeek: m.DayOfWeek.String(),
|
|
// StartTime: m.StartTime.String(),
|
|
// EndTime: m.EndTime.String(),
|
|
// StartDate: startDate,
|
|
// EndDate: endDate,
|
|
// Location: m.Location.String(),
|
|
// Notes: m.Notes.String(),
|
|
// CreatedAt: m.CreatedAt.Time(),
|
|
// }
|
|
// }
|
|
|
|
// func importantDateFromModel(m generatedmodels.ModelPublicImportantDates, memberName string) ext.ImportantDate {
|
|
// var familyMemberID *uuid.UUID
|
|
// if m.FamilyMemberID.Valid {
|
|
// id := m.FamilyMemberID.UUID()
|
|
// familyMemberID = &id
|
|
// }
|
|
|
|
// return ext.ImportantDate{
|
|
// ID: m.ID.UUID(),
|
|
// FamilyMemberID: familyMemberID,
|
|
// MemberName: memberName,
|
|
// Title: m.Title.String(),
|
|
// DateValue: m.DateValue.Time(),
|
|
// RecurringYearly: m.RecurringYearly,
|
|
// ReminderDaysBefore: int(m.ReminderDaysBefore),
|
|
// Notes: m.Notes.String(),
|
|
// CreatedAt: m.CreatedAt.Time(),
|
|
// }
|
|
// }
|
|
|
|
// func professionalContactFromModel(m generatedmodels.ModelPublicProfessionalContacts, tags []string) ext.ProfessionalContact {
|
|
// var lastContacted *time.Time
|
|
// if m.LastContacted.Valid {
|
|
// t := m.LastContacted.Time()
|
|
// lastContacted = &t
|
|
// }
|
|
|
|
// var followUpDate *time.Time
|
|
// if m.FollowUpDate.Valid {
|
|
// t := m.FollowUpDate.Time()
|
|
// followUpDate = &t
|
|
// }
|
|
|
|
// return ext.ProfessionalContact{
|
|
// ID: m.ID.UUID(),
|
|
// Name: m.Name.String(),
|
|
// Company: m.Company.String(),
|
|
// Title: m.Title.String(),
|
|
// Email: m.Email.String(),
|
|
// Phone: m.Phone.String(),
|
|
// LinkedInURL: m.LinkedinURL.String(),
|
|
// HowWeMet: m.HowWeMet.String(),
|
|
// Tags: tags,
|
|
// Notes: m.Notes.String(),
|
|
// LastContacted: lastContacted,
|
|
// FollowUpDate: followUpDate,
|
|
// CreatedAt: m.CreatedAt.Time(),
|
|
// UpdatedAt: m.UpdatedAt.Time(),
|
|
// }
|
|
// }
|
|
|
|
// func contactInteractionFromModel(m generatedmodels.ModelPublicContactInteractions) ext.ContactInteraction {
|
|
// return ext.ContactInteraction{
|
|
// ID: m.ID.UUID(),
|
|
// ContactID: m.ContactID.UUID(),
|
|
// InteractionType: m.InteractionType.String(),
|
|
// OccurredAt: m.OccurredAt.Time(),
|
|
// Summary: m.Summary.String(),
|
|
// FollowUpNeeded: m.FollowUpNeeded,
|
|
// FollowUpNotes: m.FollowUpNotes.String(),
|
|
// CreatedAt: m.CreatedAt.Time(),
|
|
// }
|
|
// }
|
|
|
|
// func opportunityFromModel(m generatedmodels.ModelPublicOpportunities) ext.Opportunity {
|
|
// var contactID *uuid.UUID
|
|
// if m.ContactID.Valid {
|
|
// id := m.ContactID.UUID()
|
|
// contactID = &id
|
|
// }
|
|
|
|
// var value *float64
|
|
// if m.Value.Valid {
|
|
// v := m.Value.Float64()
|
|
// value = &v
|
|
// }
|
|
|
|
// var expectedCloseDate *time.Time
|
|
// if m.ExpectedCloseDate.Valid {
|
|
// t := m.ExpectedCloseDate.Time()
|
|
// expectedCloseDate = &t
|
|
// }
|
|
|
|
// return ext.Opportunity{
|
|
// ID: m.ID.UUID(),
|
|
// ContactID: contactID,
|
|
// Title: m.Title.String(),
|
|
// Description: m.Description.String(),
|
|
// Stage: m.Stage.String(),
|
|
// Value: value,
|
|
// ExpectedCloseDate: expectedCloseDate,
|
|
// Notes: m.Notes.String(),
|
|
// CreatedAt: m.CreatedAt.Time(),
|
|
// UpdatedAt: m.UpdatedAt.Time(),
|
|
// }
|
|
// }
|
|
|
|
// func recipeFromModel(m generatedmodels.ModelPublicRecipes, tags []string) ext.Recipe {
|
|
// var prepTimeMinutes *int
|
|
// if m.PrepTimeMinutes.Valid {
|
|
// v := int(m.PrepTimeMinutes.Int64())
|
|
// prepTimeMinutes = &v
|
|
// }
|
|
|
|
// var cookTimeMinutes *int
|
|
// if m.CookTimeMinutes.Valid {
|
|
// v := int(m.CookTimeMinutes.Int64())
|
|
// cookTimeMinutes = &v
|
|
// }
|
|
|
|
// var servings *int
|
|
// if m.Servings.Valid {
|
|
// v := int(m.Servings.Int64())
|
|
// servings = &v
|
|
// }
|
|
|
|
// var rating *int
|
|
// if m.Rating.Valid {
|
|
// v := int(m.Rating.Int64())
|
|
// rating = &v
|
|
// }
|
|
|
|
// recipe := ext.Recipe{
|
|
// ID: m.ID.UUID(),
|
|
// Name: m.Name.String(),
|
|
// Cuisine: m.Cuisine.String(),
|
|
// PrepTimeMinutes: prepTimeMinutes,
|
|
// CookTimeMinutes: cookTimeMinutes,
|
|
// Servings: servings,
|
|
// Tags: tags,
|
|
// Rating: rating,
|
|
// Notes: m.Notes.String(),
|
|
// CreatedAt: m.CreatedAt.Time(),
|
|
// UpdatedAt: m.UpdatedAt.Time(),
|
|
// }
|
|
|
|
// if err := json.Unmarshal(m.Ingredients, &recipe.Ingredients); err != nil {
|
|
// recipe.Ingredients = []ext.Ingredient{}
|
|
// }
|
|
// if err := json.Unmarshal(m.Instructions, &recipe.Instructions); err != nil {
|
|
// recipe.Instructions = []string{}
|
|
// }
|
|
// return recipe
|
|
// }
|
|
|
|
// func mealPlanEntryFromModel(m generatedmodels.ModelPublicMealPlans, recipeName string) ext.MealPlanEntry {
|
|
// var recipeID *uuid.UUID
|
|
// if m.RecipeID.Valid {
|
|
// id := m.RecipeID.UUID()
|
|
// recipeID = &id
|
|
// }
|
|
|
|
// var servings *int
|
|
// if m.Servings.Valid {
|
|
// v := int(m.Servings.Int64())
|
|
// servings = &v
|
|
// }
|
|
|
|
// return ext.MealPlanEntry{
|
|
// ID: m.ID.UUID(),
|
|
// WeekStart: m.WeekStart.Time(),
|
|
// DayOfWeek: m.DayOfWeek.String(),
|
|
// MealType: m.MealType.String(),
|
|
// RecipeID: recipeID,
|
|
// RecipeName: recipeName,
|
|
// CustomMeal: m.CustomMeal.String(),
|
|
// Servings: servings,
|
|
// Notes: m.Notes.String(),
|
|
// CreatedAt: m.CreatedAt.Time(),
|
|
// }
|
|
// }
|
|
|
|
// func shoppingListFromModel(m generatedmodels.ModelPublicShoppingLists) ext.ShoppingList {
|
|
// list := ext.ShoppingList{
|
|
// ID: m.ID.UUID(),
|
|
// WeekStart: m.WeekStart.Time(),
|
|
// Notes: m.Notes.String(),
|
|
// CreatedAt: m.CreatedAt.Time(),
|
|
// UpdatedAt: m.UpdatedAt.Time(),
|
|
// }
|
|
// if err := json.Unmarshal(m.Items, &list.Items); err != nil {
|
|
// list.Items = []ext.ShoppingItem{}
|
|
// }
|
|
// return list
|
|
// }
|
|
|
|
func planFromModel(m generatedmodels.ModelPublicPlans, tags []string) ext.Plan {
|
|
var projectID *int64
|
|
if m.ProjectID.Valid {
|
|
id := m.ProjectID.Int64()
|
|
projectID = &id
|
|
}
|
|
|
|
var dueDate *time.Time
|
|
if m.DueDate.Valid {
|
|
t := m.DueDate.Time()
|
|
dueDate = &t
|
|
}
|
|
|
|
var completedAt *time.Time
|
|
if m.CompletedAt.Valid {
|
|
t := m.CompletedAt.Time()
|
|
completedAt = &t
|
|
}
|
|
|
|
var lastReviewedAt *time.Time
|
|
if m.LastReviewedAt.Valid {
|
|
t := m.LastReviewedAt.Time()
|
|
lastReviewedAt = &t
|
|
}
|
|
|
|
var supersedesPlanID *int64
|
|
if m.SupersedesPlanID.Valid {
|
|
id := m.SupersedesPlanID.Int64()
|
|
supersedesPlanID = &id
|
|
}
|
|
|
|
return ext.Plan{
|
|
ID: m.ID.Int64(),
|
|
GUID: m.GUID.UUID(),
|
|
Title: m.Title.String(),
|
|
Description: m.Description.String(),
|
|
Status: ext.PlanStatus(m.Status.String()),
|
|
Priority: ext.PlanPriority(m.Priority.String()),
|
|
ProjectID: projectID,
|
|
Owner: m.Owner.String(),
|
|
DueDate: dueDate,
|
|
CompletedAt: completedAt,
|
|
ReviewedBy: m.ReviewedBy.String(),
|
|
LastReviewedAt: lastReviewedAt,
|
|
SupersedesPlanID: supersedesPlanID,
|
|
Tags: tags,
|
|
CreatedAt: m.CreatedAt.Time(),
|
|
UpdatedAt: m.UpdatedAt.Time(),
|
|
}
|
|
}
|
|
|
|
func learningFromModel(m generatedmodels.ModelPublicLearnings, tags []string) ext.Learning {
|
|
var projectID *int64
|
|
if m.ProjectID.Valid {
|
|
id := m.ProjectID.Int64()
|
|
projectID = &id
|
|
}
|
|
|
|
var relatedThoughtID *int64
|
|
if m.RelatedThoughtID.Valid {
|
|
id := m.RelatedThoughtID.Int64()
|
|
relatedThoughtID = &id
|
|
}
|
|
|
|
var relatedSkillID *int64
|
|
if m.RelatedSkillID.Valid {
|
|
id := m.RelatedSkillID.Int64()
|
|
relatedSkillID = &id
|
|
}
|
|
|
|
var duplicateOfLearningID *int64
|
|
if m.DuplicateOfLearningID.Valid {
|
|
id := m.DuplicateOfLearningID.Int64()
|
|
duplicateOfLearningID = &id
|
|
}
|
|
|
|
var supersedesLearningID *int64
|
|
if m.SupersedesLearningID.Valid {
|
|
id := m.SupersedesLearningID.Int64()
|
|
supersedesLearningID = &id
|
|
}
|
|
|
|
var reviewedBy *string
|
|
if m.ReviewedBy.Valid {
|
|
value := m.ReviewedBy.String()
|
|
reviewedBy = &value
|
|
}
|
|
|
|
var reviewedAt *time.Time
|
|
if m.ReviewedAt.Valid {
|
|
t := m.ReviewedAt.Time()
|
|
reviewedAt = &t
|
|
}
|
|
|
|
return ext.Learning{
|
|
ID: m.ID.Int64(),
|
|
GUID: m.GUID.UUID(),
|
|
Summary: m.Summary.String(),
|
|
Details: m.Details.String(),
|
|
Category: m.Category.String(),
|
|
Area: m.Area.String(),
|
|
Status: ext.LearningStatus(m.Status.String()),
|
|
Priority: ext.LearningPriority(m.Priority.String()),
|
|
Confidence: ext.LearningEvidenceLevel(m.Confidence.String()),
|
|
ActionRequired: m.ActionRequired,
|
|
SourceType: m.SourceType.String(),
|
|
SourceRef: m.SourceRef.String(),
|
|
ProjectID: projectID,
|
|
RelatedThoughtID: relatedThoughtID,
|
|
RelatedSkillID: relatedSkillID,
|
|
ReviewedBy: reviewedBy,
|
|
ReviewedAt: reviewedAt,
|
|
DuplicateOfLearningID: duplicateOfLearningID,
|
|
SupersedesLearningID: supersedesLearningID,
|
|
Tags: tags,
|
|
CreatedAt: m.CreatedAt.Time(),
|
|
UpdatedAt: m.UpdatedAt.Time(),
|
|
}
|
|
}
|