181 lines
8.0 KiB
Go
181 lines
8.0 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
|
|
"apskel-pos-be/internal/appcontext"
|
|
"apskel-pos-be/internal/constants"
|
|
"apskel-pos-be/internal/contract"
|
|
"apskel-pos-be/internal/processor"
|
|
"apskel-pos-be/internal/transformer"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type CashAdvanceService interface {
|
|
CreateCashAdvance(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateCashAdvanceRequest) *contract.Response
|
|
UpdateCashAdvance(ctx context.Context, apctx *appcontext.ContextInfo, id uuid.UUID, req *contract.UpdateCashAdvanceRequest) *contract.Response
|
|
DeleteCashAdvance(ctx context.Context, apctx *appcontext.ContextInfo, id uuid.UUID) *contract.Response
|
|
GetCashAdvanceByID(ctx context.Context, apctx *appcontext.ContextInfo, id uuid.UUID) *contract.Response
|
|
ListCashAdvances(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.ListCashAdvancesRequest) *contract.Response
|
|
UpdateCashAdvanceStatus(ctx context.Context, apctx *appcontext.ContextInfo, id uuid.UUID, status string) *contract.Response
|
|
ListCashAdvanceTeams(ctx context.Context, apctx *appcontext.ContextInfo) *contract.Response
|
|
}
|
|
|
|
type CashAdvanceServiceImpl struct {
|
|
cashAdvanceProcessor processor.CashAdvanceProcessor
|
|
}
|
|
|
|
func NewCashAdvanceService(cashAdvanceProcessor processor.CashAdvanceProcessor) *CashAdvanceServiceImpl {
|
|
return &CashAdvanceServiceImpl{cashAdvanceProcessor: cashAdvanceProcessor}
|
|
}
|
|
|
|
func (s *CashAdvanceServiceImpl) CreateCashAdvance(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.CreateCashAdvanceRequest) *contract.Response {
|
|
modelReq, err := transformer.CreateCashAdvanceRequestToModel(req)
|
|
if err != nil {
|
|
errorResp := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.CashAdvanceServiceEntity, "Invalid date format. Use YYYY-MM-DD format")
|
|
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
|
|
}
|
|
|
|
cashAdvance, err := s.cashAdvanceProcessor.CreateCashAdvance(ctx, apctx.OrganizationID, outletFromContext(apctx), modelReq)
|
|
if err != nil {
|
|
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CashAdvanceServiceEntity, err.Error())
|
|
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
|
|
}
|
|
|
|
return contract.BuildSuccessResponse(transformer.CashAdvanceModelResponseToResponse(cashAdvance))
|
|
}
|
|
|
|
func (s *CashAdvanceServiceImpl) UpdateCashAdvance(ctx context.Context, apctx *appcontext.ContextInfo, id uuid.UUID, req *contract.UpdateCashAdvanceRequest) *contract.Response {
|
|
modelReq, err := transformer.UpdateCashAdvanceRequestToModel(req)
|
|
if err != nil {
|
|
errorResp := contract.NewResponseError(constants.MalformedFieldErrorCode, constants.CashAdvanceServiceEntity, "Invalid date format. Use YYYY-MM-DD format")
|
|
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
|
|
}
|
|
|
|
cashAdvance, err := s.cashAdvanceProcessor.UpdateCashAdvance(ctx, id, apctx.OrganizationID, modelReq)
|
|
if err != nil {
|
|
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CashAdvanceServiceEntity, err.Error())
|
|
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
|
|
}
|
|
|
|
return contract.BuildSuccessResponse(transformer.CashAdvanceModelResponseToResponse(cashAdvance))
|
|
}
|
|
|
|
func (s *CashAdvanceServiceImpl) DeleteCashAdvance(ctx context.Context, apctx *appcontext.ContextInfo, id uuid.UUID) *contract.Response {
|
|
if err := s.cashAdvanceProcessor.DeleteCashAdvance(ctx, id, apctx.OrganizationID); err != nil {
|
|
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CashAdvanceServiceEntity, err.Error())
|
|
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
|
|
}
|
|
|
|
return contract.BuildSuccessResponse(map[string]interface{}{
|
|
"message": "Cash advance deleted successfully",
|
|
})
|
|
}
|
|
|
|
func (s *CashAdvanceServiceImpl) GetCashAdvanceByID(ctx context.Context, apctx *appcontext.ContextInfo, id uuid.UUID) *contract.Response {
|
|
cashAdvance, err := s.cashAdvanceProcessor.GetCashAdvanceByID(ctx, id, apctx.OrganizationID)
|
|
if err != nil {
|
|
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CashAdvanceServiceEntity, err.Error())
|
|
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
|
|
}
|
|
|
|
return contract.BuildSuccessResponse(transformer.CashAdvanceModelResponseToResponse(cashAdvance))
|
|
}
|
|
|
|
func (s *CashAdvanceServiceImpl) ListCashAdvances(ctx context.Context, apctx *appcontext.ContextInfo, req *contract.ListCashAdvancesRequest) *contract.Response {
|
|
modelReq := transformer.ListCashAdvancesRequestToModel(req)
|
|
|
|
filters := make(map[string]interface{})
|
|
if modelReq.Search != "" {
|
|
filters["search"] = modelReq.Search
|
|
}
|
|
if modelReq.Status != "" {
|
|
filters["status"] = modelReq.Status
|
|
}
|
|
if modelReq.SettlementStatus != "" {
|
|
filters["settlement_status"] = modelReq.SettlementStatus
|
|
}
|
|
if modelReq.TeamScope != "" {
|
|
filters["team_scope"] = modelReq.TeamScope
|
|
}
|
|
if modelReq.TeamCategoryID != nil {
|
|
filters["team_category_id"] = *modelReq.TeamCategoryID
|
|
}
|
|
// team spells out the same two filters in one value; the validator has already
|
|
// ruled out sending it together with them.
|
|
switch modelReq.Team {
|
|
case "":
|
|
case constants.PurchaseTeamScopeCentral:
|
|
filters["team_scope"] = constants.PurchaseTeamScopeCentral
|
|
default:
|
|
if teamCategoryID, err := uuid.Parse(modelReq.Team); err == nil {
|
|
filters["team_scope"] = constants.PurchaseTeamScopeCategory
|
|
filters["team_category_id"] = teamCategoryID
|
|
}
|
|
}
|
|
if modelReq.StartDate != nil {
|
|
filters["start_date"] = *modelReq.StartDate
|
|
}
|
|
if modelReq.EndDate != nil {
|
|
filters["end_date"] = *modelReq.EndDate
|
|
}
|
|
// Cash belongs to the drawer it came out of, so a user signed in to one outlet
|
|
// only sees that outlet's cash advances.
|
|
if outletID := outletFromContext(apctx); outletID != nil {
|
|
filters["outlet_id"] = *outletID
|
|
}
|
|
|
|
cashAdvances, totalPages, err := s.cashAdvanceProcessor.ListCashAdvances(ctx, apctx.OrganizationID, filters, modelReq.Page, modelReq.Limit)
|
|
if err != nil {
|
|
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CashAdvanceServiceEntity, err.Error())
|
|
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
|
|
}
|
|
|
|
responses := make([]contract.CashAdvanceResponse, len(cashAdvances))
|
|
for i, cashAdvance := range cashAdvances {
|
|
if response := transformer.CashAdvanceModelResponseToResponse(cashAdvance); response != nil {
|
|
responses[i] = *response
|
|
}
|
|
}
|
|
|
|
return contract.BuildSuccessResponse(contract.ListCashAdvancesResponse{
|
|
CashAdvances: responses,
|
|
TotalCount: len(responses),
|
|
Page: modelReq.Page,
|
|
Limit: modelReq.Limit,
|
|
TotalPages: totalPages,
|
|
})
|
|
}
|
|
|
|
func (s *CashAdvanceServiceImpl) UpdateCashAdvanceStatus(ctx context.Context, apctx *appcontext.ContextInfo, id uuid.UUID, status string) *contract.Response {
|
|
cashAdvance, err := s.cashAdvanceProcessor.UpdateCashAdvanceStatus(ctx, id, apctx.OrganizationID, status)
|
|
if err != nil {
|
|
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CashAdvanceServiceEntity, err.Error())
|
|
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
|
|
}
|
|
|
|
return contract.BuildSuccessResponse(transformer.CashAdvanceModelResponseToResponse(cashAdvance))
|
|
}
|
|
|
|
func (s *CashAdvanceServiceImpl) ListCashAdvanceTeams(ctx context.Context, apctx *appcontext.ContextInfo) *contract.Response {
|
|
teams, err := s.cashAdvanceProcessor.ListCashAdvanceTeams(ctx, apctx.OrganizationID, outletFromContext(apctx))
|
|
if err != nil {
|
|
errorResp := contract.NewResponseError(constants.InternalServerErrorCode, constants.CashAdvanceServiceEntity, err.Error())
|
|
return contract.BuildErrorResponse([]*contract.ResponseError{errorResp})
|
|
}
|
|
|
|
return contract.BuildSuccessResponse(transformer.ListPurchaseTeamsModelResponseToResponse(teams))
|
|
}
|
|
|
|
// outletFromContext reads the caller's outlet as an optional value: an organization
|
|
// level user has none, and uuid.Nil is how that arrives on the context.
|
|
func outletFromContext(apctx *appcontext.ContextInfo) *uuid.UUID {
|
|
if apctx.OutletID == uuid.Nil {
|
|
return nil
|
|
}
|
|
|
|
outletID := apctx.OutletID
|
|
return &outletID
|
|
}
|