PAMUKKALE Daphnis nerii __
PAMUKKALE Daphnis nerii __
Teslim alım stok durumu yüklenemedi
"Daphnis nerii", commonly known as the oleander hawk-moth or army green moth, is a large moth of the Sphingidae family. It is notable for its striking appearance and size. The moth has a robust body and wings that are predominantly olive green, with white and pinkish markings and a distinct pale line extending from the head to the rear. The hindwings are a brighter pink to red, adding a vivid contrast to the muted tones of the forewings.
The oleander hawk-moth is widespread across parts of Africa, Asia, and Southern Europe, and has even been found as far afield as the Hawaiian Islands and parts of the British Isles, often migrating considerable distances. It is named after its primary larval food plant, the oleander, which contains toxic compounds that the larvae are able to ingest, making them unpalatable to many predators.
This moth is nocturnal and is often seen feeding on the nectar of strong-scented flowers at night. The presence of Daphnis nerii in an area is often a sign of a healthy oleander population, and its remarkable migratory patterns are of interest to scientists studying ecological connectivity and the effects of climate change on migratory species.
# Comments Module — Technical Documentation (EN)
---
## 1. Introduction
### Purpose
The Comments module provides create, list, and delete operations for comments related to educational activities (lessons) and/or leave requests. Attachments (documents) are supported: they are stored in the database as Base64 content and linked to the comment.
### Key features
- Create a comment with optional attachments (multipart/form-data)
- List comments with filters by author, employee, and activity; each comment includes a “lightweight” list of documents (without Base64)
- Delete a comment together with all related documents (within a transaction)
- Enriched list output: author name, chartered (accountant) name, and activity display name
---
## 2. Architecture
```
┌──────────────────┐ HTTP ┌──────────────────────────┐ GORM ┌───────────────────────┐
│ Client │ ─────────────▶ │ ginserver/handlers │ ───────────▶ │ service/comment │
└──────────────────┘ (REST) │ Create/List/Delete │ │ Add/List/Delete │
└────────────┬─────────────┘ └──────────┬────────────┘
▼ ▼
database.CommentModel database.DocumentModel
database.LessonModel database.UserModel
database.CharteredAccountantModel (relations/attachments)
```
Components:
- DB model: `database.CommentModel` (table `Comments`)
- Attachments: `database.DocumentModel` (relation `Documents` by `CommentID`)
- Service: `service/comment/service.go` (`AddComment`, `CommentsList`, `DeleteComment`)
- HTTP handler: `ginserver/handlers/comments.go` (`POST /v1/comments`, `GET /v1/comments`, `DELETE /v1/comments/{id}`)
- Additional enrichment: `database.LessonModel` (activity name), `database.UserModel` (author name), `database.CharteredAccountantModel` (chartered name)
---
## 3. Data Model
Table: `Comments`
```go
// database/comment_model.go
type CommentModel struct {
CommentID uint `gorm:"primaryKey;column:CommentID"`
CreatorEnum string `gorm:"column:CreatorEnum"` // author's EmployeeNum
EmployeeNum string `gorm:"column:EmployeeNum"`
EducationalActivityID uint `gorm:"column:EducationalActivityID"`
LeaveID uint `gorm:"column:LeaveID"`
Content string `gorm:"type:text;column:Content"`
Status string `gorm:"type:text;column:Status"`
Subject string `gorm:"type:text;column:Subject"`
Documents []DocumentModel `gorm:"ForeignKey:CommentID"`
CreatedAt time.Time `gorm:"column:CreatedAt"`
UpdatedAt time.Time `gorm:"column:UpdatedAt"`
}
func (CommentModel) TableName() string { return "Comments" }
```
Notes:
- Related `Documents` are preloaded for list responses with `Omit("Base64Content")` to avoid returning heavy payloads
- `CreatorEnum` stores the author's `EmployeeNum`
Enriched list item shape:
```go
// ginserver/models/comments.go (conceptual)
type CommentWithActivityName struct {
CommentID uint
CreatorEnum string
CreatorName string
EmployeeNum string
CharteredName string
EducationalActivityID uint
EducationActivityName string
LeaveID uint
Subject string
Content string
Documents []database.DocumentModel // without Base64Content
CreatedAt time.Time
UpdatedAt time.Time
}
```
---
## 4. HTTP API
### 4.1 CreateComment — POST `/v1/comments`
- **Description**: Creates a new comment; supports uploading multiple files as attachments
- **Request body**: `multipart/form-data`
- `employee_num` (string, required)
- `educational_activity_id` (int, optional)
- `content` (string, required)
- `documents` (file, optional, multiple)
- **Authentication**: required (current user is used as the author)
- **Responses**:
- `200 OK`: `{ "message": { ... i18n ... } }`
- `400 Bad Request`: invalid `educational_activity_id`, unsupported file type, file read error
- `500 Internal Server Error`: failed to persist comment or document
Example:
```bash
curl -X POST 'http://localhost:8080/v1/comments' \
-H 'Authorization: Bearer ' \
-F 'employee_num=E123' \
-F 'educational_activity_id=456' \
-F 'content=Please review the attached syllabus' \
-F 'documents=@/path/to/file1.pdf' \
-F 'documents=@/path/to/image.png'
```
Supported MIME types (validated in handler):
- `application/pdf`, `application/msword`, `application/vnd.openxmlformats-officedocument.wordprocessingml.document`
- `application/vnd.ms-excel`, `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`
- `image/png`, `image/jpeg`, `image/gif`, `text/plain`
- `application/octet-stream` (for tests)
### 4.2 CommentsList — GET `/v1/comments`
- **Description**: Returns a list of comments with attachments (without Base64) and enriched fields
- **Query parameters**:
- `creator_enum` (string, optional)
- `employee_num` (string, optional)
- `educational_activity_id` (uint, optional)
- **Responses**:
- `200 OK`: `{ "comments": [ CommentWithActivityName, ... ] }`
- `400 Bad Request`: query binding error
- `500 Internal Server Error`: internal service/DB error
Sample response:
```json
{
"comments": [
{
"CommentID": 101,
"CreatorEnum": "A001",
"CreatorName": "Admin User",
"EmployeeNum": "E123",
"CharteredName": "John Accountant",
"EducationalActivityID": 456,
"EducationActivityName": "Seminar: Tax Law",
"LeaveID": 0,
"Subject": "",
"Content": "Please review the attached syllabus",
"Documents": [ { "FileName": "file1.pdf", "MimeType": "application/pdf" } ],
"CreatedAt": "2025-09-09T10:00:00Z",
"UpdatedAt": "2025-09-09T10:00:00Z"
}
]
}
```
Filtering notes:
- If `EducationalActivityID` is present, the current implementation applies a numeric `LIKE` filter; then clears the field before applying `Where(filter)`
- Documents are preloaded with `Omit("Base64Content")`
### 4.3 DeleteComment — DELETE `/v1/comments/{id}`
- **Description**: Deletes a comment by `id` together with all related documents in a single transaction
- **Path parameter**: `id` (uint, required)
- **Responses**:
- `200 OK`: `{ "message": { ... i18n ... } }`
- `400 Bad Request`: invalid `id`
- `500 Internal Server Error`: failed to delete the comment or its documents
---
## 5. Service (service/comment)
Interface and implementation:
```go
type Comment interface {
AddComment(comment *database.CommentModel) error
CommentsList(filter *database.CommentModel) ([]models.CommentWithActivityName, error)
DeleteComment(ctx context.Context, id uint) error
}
// Key implementation points:
// - AddComment: sets CreatedAt = time.Now(), then Create(comment)
// - CommentsList:
// * Preload("Documents", db.Omit("Base64Content"))
// * Optional numeric LIKE filter for EducationalActivityID, then Where(filter)
// * Enriches output: loads activity names (Lesson.ActivityName),
// author name (User.Name by CreatorEnum), and chartered name
// (CharteredAccountant.CharteredName by EmployeeNum)
// - DeleteComment: transactionally deletes documents by CommentID then the comment itself
```
Service errors are propagated to handlers and logged there.
---
## 6. Validation and Error Handling
- CreateComment:
- Validates `educational_activity_id` (if provided)
- Validates MIME type of each file
- File open/read errors return `400`
- Persist errors for comment/documents return `500`
- CommentsList:
- Invalid query parameters (binding) — `400`
- DB/enrichment errors — `500`
- DeleteComment:
- Invalid `id` — `400`
- Transactional delete error — `500`
Note: The current version does not strictly validate non-empty `content`/`employee_num` in the handler; strengthen input validation if required.
---
## 7. Security and Access
- All operations assume authentication: the comment author is taken from the request context (`contextValueUser` → `UserModel`)
- Role-based authorization is left to middleware/caller policy (e.g., admins may create/delete; users read their own)
- Avoid sending sensitive data in the body or attachments unless necessary
---
## 8. Integrations and Extensions
- Attachments: persisted through the document service; Base64 is not returned in list responses
- Entity enrichment: via `LessonModel`, `UserModel`, `CharteredAccountantModel`
- Notifications: the handler contains commented-out mailer integration (`utils.BuildCommentLessonEmailBody`, `MailServ.AddMail`) — can be re-enabled to trigger email notifications when adding a comment
---
## 9. Testing (recommendations)
- Service unit tests:
- Successful comment creation
- List with filters; ensure attachment Base64 is not returned; verify enrichment fields
- Transactional delete of a comment and related documents
- Handler integration tests:
- `POST /v1/comments` with multiple files; verify error codes for unsupported types
- `GET /v1/comments` with various filter combinations
- `DELETE /v1/comments/{id}` — positive and negative cases
Run tests:
```bash
go test ./...
```
---
## 10. Usage (cheat sheet)
```bash
# Create a comment with an attachment
curl -X POST 'http://localhost:8080/v1/comments' \
-H 'Authorization: Bearer ' \
-F 'employee_num=E123' \
-F 'educational_activity_id=456' \
-F 'content=Please review the attached syllabus' \
-F 'documents=@/path/to/file1.pdf'
# Get comments by employee
curl -G 'http://localhost:8080/v1/comments' \
--data-urlencode 'employee_num=E123'
# Delete a comment
curl -X DELETE 'http://localhost:8080/v1/comments/101'
```
---
Paylaşmak