Initial commit: MyCrib API in Go

Complete rewrite of Django REST API to Go with:
- Gin web framework for HTTP routing
- GORM for database operations
- GoAdmin for admin panel
- Gorush integration for push notifications
- Redis for caching and job queues

Features implemented:
- User authentication (login, register, logout, password reset)
- Residence management (CRUD, sharing, share codes)
- Task management (CRUD, kanban board, completions)
- Contractor management (CRUD, specialties)
- Document management (CRUD, warranties)
- Notifications (preferences, push notifications)
- Subscription management (tiers, limits)

Infrastructure:
- Docker Compose for local development
- Database migrations and seed data
- Admin panel for data management

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-11-26 20:07:16 -06:00
commit 1f12f3f62a
78 changed files with 13821 additions and 0 deletions

View File

@@ -0,0 +1,111 @@
package responses
import (
"time"
"github.com/shopspring/decimal"
"github.com/treytartt/mycrib-api/internal/models"
)
// DocumentUserResponse represents a user in document context
type DocumentUserResponse struct {
ID uint `json:"id"`
Username string `json:"username"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
}
// DocumentResponse represents a document in the API response
type DocumentResponse struct {
ID uint `json:"id"`
ResidenceID uint `json:"residence_id"`
CreatedByID uint `json:"created_by_id"`
CreatedBy *DocumentUserResponse `json:"created_by,omitempty"`
Title string `json:"title"`
Description string `json:"description"`
DocumentType models.DocumentType `json:"document_type"`
FileURL string `json:"file_url"`
FileName string `json:"file_name"`
FileSize *int64 `json:"file_size"`
MimeType string `json:"mime_type"`
PurchaseDate *time.Time `json:"purchase_date"`
ExpiryDate *time.Time `json:"expiry_date"`
PurchasePrice *decimal.Decimal `json:"purchase_price"`
Vendor string `json:"vendor"`
SerialNumber string `json:"serial_number"`
ModelNumber string `json:"model_number"`
TaskID *uint `json:"task_id"`
IsActive bool `json:"is_active"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// DocumentListResponse represents a paginated list of documents
type DocumentListResponse struct {
Count int `json:"count"`
Next *string `json:"next"`
Previous *string `json:"previous"`
Results []DocumentResponse `json:"results"`
}
// === Factory Functions ===
// NewDocumentUserResponse creates a DocumentUserResponse from a User model
func NewDocumentUserResponse(u *models.User) *DocumentUserResponse {
if u == nil {
return nil
}
return &DocumentUserResponse{
ID: u.ID,
Username: u.Username,
FirstName: u.FirstName,
LastName: u.LastName,
}
}
// NewDocumentResponse creates a DocumentResponse from a Document model
func NewDocumentResponse(d *models.Document) DocumentResponse {
resp := DocumentResponse{
ID: d.ID,
ResidenceID: d.ResidenceID,
CreatedByID: d.CreatedByID,
Title: d.Title,
Description: d.Description,
DocumentType: d.DocumentType,
FileURL: d.FileURL,
FileName: d.FileName,
FileSize: d.FileSize,
MimeType: d.MimeType,
PurchaseDate: d.PurchaseDate,
ExpiryDate: d.ExpiryDate,
PurchasePrice: d.PurchasePrice,
Vendor: d.Vendor,
SerialNumber: d.SerialNumber,
ModelNumber: d.ModelNumber,
TaskID: d.TaskID,
IsActive: d.IsActive,
CreatedAt: d.CreatedAt,
UpdatedAt: d.UpdatedAt,
}
if d.CreatedBy.ID != 0 {
resp.CreatedBy = NewDocumentUserResponse(&d.CreatedBy)
}
return resp
}
// NewDocumentListResponse creates a DocumentListResponse from a slice of documents
func NewDocumentListResponse(documents []models.Document) DocumentListResponse {
results := make([]DocumentResponse, len(documents))
for i, d := range documents {
results[i] = NewDocumentResponse(&d)
}
return DocumentListResponse{
Count: len(documents),
Next: nil,
Previous: nil,
Results: results,
}
}