feature/expense #13

Merged
aefril merged 10 commits from feature/expense into main 2026-06-01 17:20:29 +00:00
10 changed files with 32 additions and 2 deletions
Showing only changes of commit a55a3f4ee2 - Show all commits

View File

@ -7,6 +7,7 @@ import (
)
type CreateExpenseRequest struct {
ExpenseName string `json:"expense_name" validate:"required"`
Receiver string `json:"receiver" validate:"required"`
TransactionDate string `json:"transaction_date" validate:"required"`
CodeNumber string `json:"code_number" validate:"required"`
@ -24,6 +25,7 @@ type CreateExpenseItemRequest struct {
}
type UpdateExpenseRequest struct {
ExpenseName *string `json:"expense_name,omitempty"`
Receiver *string `json:"receiver,omitempty"`
TransactionDate *string `json:"transaction_date,omitempty"`
CodeNumber *string `json:"code_number,omitempty"`
@ -45,6 +47,7 @@ type ExpenseResponse struct {
ID uuid.UUID `json:"id"`
OrganizationID uuid.UUID `json:"organization_id"`
OutletID uuid.UUID `json:"outlet_id"`
ExpenseName string `json:"expense_name"`
Receiver string `json:"receiver"`
TransactionDate time.Time `json:"transaction_date"`
CodeNumber string `json:"code_number"`

View File

@ -12,6 +12,7 @@ type Expense struct {
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
OrganizationID uuid.UUID `gorm:"type:uuid;not null;index" json:"organization_id"`
OutletID uuid.UUID `gorm:"type:uuid;not null;index" json:"outlet_id"`
ExpenseName string `gorm:"not null;size:255" json:"expense_name"`
Receiver string `gorm:"not null;size:255" json:"receiver"`
TransactionDate time.Time `gorm:"type:date;not null" json:"transaction_date"`
CodeNumber string `gorm:"not null;size:50" json:"code_number"`

View File

@ -14,6 +14,7 @@ func ExpenseEntityToModel(entity *entities.Expense) *models.Expense {
ID: entity.ID,
OrganizationID: entity.OrganizationID,
OutletID: entity.OutletID,
ExpenseName: entity.ExpenseName,
Receiver: entity.Receiver,
TransactionDate: entity.TransactionDate,
CodeNumber: entity.CodeNumber,
@ -35,6 +36,7 @@ func ExpenseModelToEntity(model *models.Expense) *entities.Expense {
ID: model.ID,
OrganizationID: model.OrganizationID,
OutletID: model.OutletID,
ExpenseName: model.ExpenseName,
Receiver: model.Receiver,
TransactionDate: model.TransactionDate,
CodeNumber: model.CodeNumber,
@ -56,6 +58,7 @@ func ExpenseEntityToResponse(entity *entities.Expense) *models.ExpenseResponse {
ID: entity.ID,
OrganizationID: entity.OrganizationID,
OutletID: entity.OutletID,
ExpenseName: entity.ExpenseName,
Receiver: entity.Receiver,
TransactionDate: entity.TransactionDate,
CodeNumber: entity.CodeNumber,

View File

@ -10,6 +10,7 @@ type Expense struct {
ID uuid.UUID `json:"id"`
OrganizationID uuid.UUID `json:"organization_id"`
OutletID uuid.UUID `json:"outlet_id"`
ExpenseName string `json:"expense_name"`
Receiver string `json:"receiver"`
TransactionDate time.Time `json:"transaction_date"`
CodeNumber string `json:"code_number"`
@ -35,6 +36,7 @@ type ExpenseResponse struct {
ID uuid.UUID `json:"id"`
OrganizationID uuid.UUID `json:"organization_id"`
OutletID uuid.UUID `json:"outlet_id"`
ExpenseName string `json:"expense_name"`
Receiver string `json:"receiver"`
TransactionDate time.Time `json:"transaction_date"`
CodeNumber string `json:"code_number"`
@ -59,6 +61,7 @@ type ExpenseItemResponse struct {
}
type CreateExpenseRequest struct {
ExpenseName string `json:"expense_name"`
Receiver string `json:"receiver"`
TransactionDate string `json:"transaction_date"`
CodeNumber string `json:"code_number"`
@ -76,6 +79,7 @@ type CreateExpenseItemRequest struct {
}
type UpdateExpenseRequest struct {
ExpenseName *string `json:"expense_name,omitempty"`
Receiver *string `json:"receiver,omitempty"`
TransactionDate *string `json:"transaction_date,omitempty"`
CodeNumber *string `json:"code_number,omitempty"`

View File

@ -44,6 +44,7 @@ func (p *ExpenseProcessorImpl) CreateExpense(ctx context.Context, organizationID
expenseEntity := &entities.Expense{
OrganizationID: organizationID,
OutletID: outletID,
ExpenseName: req.ExpenseName,
Receiver: req.Receiver,
TransactionDate: transactionDate,
CodeNumber: req.CodeNumber,
@ -90,6 +91,9 @@ func (p *ExpenseProcessorImpl) UpdateExpense(ctx context.Context, id, organizati
return nil, fmt.Errorf("expense not found: %w", err)
}
if req.ExpenseName != nil {
expenseEntity.ExpenseName = *req.ExpenseName
}
if req.Receiver != nil {
expenseEntity.Receiver = *req.Receiver
}

View File

@ -67,8 +67,8 @@ func (r *ExpenseRepositoryImpl) List(ctx context.Context, organizationID uuid.UU
case "search":
if searchStr, ok := value.(string); ok && searchStr != "" {
searchPattern := "%" + strings.ToLower(searchStr) + "%"
query = query.Where("LOWER(receiver) LIKE ? OR LOWER(code_number) LIKE ? OR LOWER(description) LIKE ?",
searchPattern, searchPattern, searchPattern)
query = query.Where("LOWER(expense_name) LIKE ? OR LOWER(receiver) LIKE ? OR LOWER(code_number) LIKE ? OR LOWER(description) LIKE ?",
searchPattern, searchPattern, searchPattern, searchPattern)
}
case "outlet_id":
if outletID, ok := value.(uuid.UUID); ok {

View File

@ -12,6 +12,7 @@ func CreateExpenseRequestToModel(req *contract.CreateExpenseRequest) *models.Cre
}
return &models.CreateExpenseRequest{
ExpenseName: req.ExpenseName,
Receiver: req.Receiver,
TransactionDate: req.TransactionDate,
CodeNumber: req.CodeNumber,
@ -33,6 +34,7 @@ func CreateExpenseItemRequestToModel(req *contract.CreateExpenseItemRequest) mod
func UpdateExpenseRequestToModel(req *contract.UpdateExpenseRequest) *models.UpdateExpenseRequest {
modelReq := &models.UpdateExpenseRequest{
ExpenseName: req.ExpenseName,
Receiver: req.Receiver,
TransactionDate: req.TransactionDate,
CodeNumber: req.CodeNumber,
@ -84,6 +86,7 @@ func ExpenseModelResponseToResponse(expense *models.ExpenseResponse) *contract.E
ID: expense.ID,
OrganizationID: expense.OrganizationID,
OutletID: expense.OutletID,
ExpenseName: expense.ExpenseName,
Receiver: expense.Receiver,
TransactionDate: expense.TransactionDate,
CodeNumber: expense.CodeNumber,

View File

@ -28,6 +28,10 @@ func (v *ExpenseValidatorImpl) ValidateCreateExpenseRequest(req *contract.Create
return errors.New("request body is required"), constants.MissingFieldErrorCode
}
if strings.TrimSpace(req.ExpenseName) == "" {
return errors.New("expense_name is required"), constants.MissingFieldErrorCode
}
if strings.TrimSpace(req.Receiver) == "" {
return errors.New("receiver is required"), constants.MissingFieldErrorCode
}
@ -80,6 +84,10 @@ func (v *ExpenseValidatorImpl) ValidateUpdateExpenseRequest(req *contract.Update
return errors.New("request body is required"), constants.MissingFieldErrorCode
}
if req.ExpenseName != nil && strings.TrimSpace(*req.ExpenseName) == "" {
return errors.New("expense_name cannot be empty"), constants.MalformedFieldErrorCode
}
if req.Receiver != nil && strings.TrimSpace(*req.Receiver) == "" {
return errors.New("receiver cannot be empty"), constants.MalformedFieldErrorCode
}

View File

@ -0,0 +1,2 @@
DROP INDEX IF EXISTS idx_expenses_expense_name;
ALTER TABLE expenses DROP COLUMN expense_name;

View File

@ -0,0 +1,2 @@
ALTER TABLE expenses ADD COLUMN expense_name VARCHAR(255) NOT NULL DEFAULT '';
CREATE INDEX idx_expenses_expense_name ON expenses(expense_name);