github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/db/task.go (about)

     1  // This file is part of the Smart Home
     2  // Program complex distribution https://github.com/e154/smart-home
     3  // Copyright (C) 2016-2023, Filippov Alex
     4  //
     5  // This library is free software: you can redistribute it and/or
     6  // modify it under the terms of the GNU Lesser General Public
     7  // License as published by the Free Software Foundation; either
     8  // version 3 of the License, or (at your option) any later version.
     9  //
    10  // This library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13  // Library General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public
    16  // License along with this library.  If not, see
    17  // <https://www.gnu.org/licenses/>.
    18  
    19  package db
    20  
    21  import (
    22  	"context"
    23  	"fmt"
    24  	"time"
    25  
    26  	"github.com/e154/smart-home/common/apperr"
    27  
    28  	"github.com/e154/smart-home/common"
    29  	"github.com/pkg/errors"
    30  	"gorm.io/gorm"
    31  )
    32  
    33  // Tasks ...
    34  type Tasks struct {
    35  	Db *gorm.DB
    36  }
    37  
    38  // Task ...
    39  type Task struct {
    40  	Id          int64 `gorm:"primary_key"`
    41  	Name        string
    42  	Description string
    43  	Enabled     bool
    44  	Condition   common.ConditionType
    45  	Conditions  []*Condition `gorm:"many2many:task_conditions;"`
    46  	Actions     []*Action    `gorm:"many2many:task_actions;"`
    47  	Triggers    []*Trigger   `gorm:"many2many:task_triggers;"`
    48  	AreaId      *int64
    49  	Area        *Area
    50  	CreatedAt   time.Time `gorm:"<-:create"`
    51  	UpdatedAt   time.Time
    52  }
    53  
    54  // TableName ...
    55  func (d *Task) TableName() string {
    56  	return "tasks"
    57  }
    58  
    59  // Add ...
    60  func (n Tasks) Add(ctx context.Context, task *Task) (id int64, err error) {
    61  	err = n.Db.WithContext(ctx).
    62  		Omit("Triggers.*", "Conditions.*", "Actions.*").
    63  		Create(&task).Error
    64  	if err != nil {
    65  		err = errors.Wrap(apperr.ErrTaskAdd, err.Error())
    66  		return
    67  	}
    68  	id = task.Id
    69  	return
    70  }
    71  
    72  // GetById ...
    73  func (n Tasks) GetById(ctx context.Context, taskId int64) (task *Task, err error) {
    74  	task = &Task{}
    75  	err = n.Db.WithContext(ctx).Model(task).
    76  		Where("id = ?", taskId).
    77  		Preload("Triggers").
    78  		Preload("Triggers.Script").
    79  		Preload("Triggers.Entities").
    80  		Preload("Conditions").
    81  		Preload("Conditions.Script").
    82  		Preload("Actions").
    83  		Preload("Actions.Script").
    84  		Preload("Actions.Entity").
    85  		Preload("Area").
    86  		First(task).Error
    87  	if err != nil {
    88  		if errors.Is(err, gorm.ErrRecordNotFound) {
    89  			err = errors.Wrap(apperr.ErrTaskNotFound, fmt.Sprintf("id \"%d\"", taskId))
    90  			return
    91  		}
    92  		err = errors.Wrap(apperr.ErrTaskGet, err.Error())
    93  		return
    94  	}
    95  
    96  	return
    97  }
    98  
    99  // Update ...
   100  func (n Tasks) Update(ctx context.Context, task *Task) (err error) {
   101  	err = n.Db.WithContext(ctx).
   102  		Omit("Triggers.*", "Conditions.*", "Actions.*").
   103  		Save(task).Error
   104  	if err != nil {
   105  		err = errors.Wrap(apperr.ErrTaskUpdate, err.Error())
   106  	}
   107  	return
   108  }
   109  
   110  // Delete ...
   111  func (n Tasks) Delete(ctx context.Context, id int64) (err error) {
   112  	if err = n.Db.WithContext(ctx).Delete(&Task{Id: id}).Error; err != nil {
   113  		err = errors.Wrap(apperr.ErrTaskDelete, err.Error())
   114  		return
   115  	}
   116  	return
   117  }
   118  
   119  // Enable ...
   120  func (n Tasks) Enable(ctx context.Context, id int64) (err error) {
   121  	if err = n.Db.WithContext(ctx).Model(&Task{Id: id}).Updates(map[string]interface{}{"enabled": true}).Error; err != nil {
   122  		err = errors.Wrap(apperr.ErrTaskUpdate, err.Error())
   123  		return
   124  	}
   125  	return
   126  }
   127  
   128  // Disable ...
   129  func (n Tasks) Disable(ctx context.Context, id int64) (err error) {
   130  	if err = n.Db.WithContext(ctx).Model(&Task{Id: id}).Updates(map[string]interface{}{"enabled": false}).Error; err != nil {
   131  		err = errors.Wrap(apperr.ErrTaskUpdate, err.Error())
   132  		return
   133  	}
   134  	return
   135  }
   136  
   137  // List ...
   138  func (n Tasks) List(ctx context.Context, limit, offset int, orderBy, sort string, onlyEnabled bool) (list []*Task, total int64, err error) {
   139  
   140  	list = make([]*Task, 0)
   141  	q := n.Db.WithContext(ctx).Model(&Task{})
   142  
   143  	if onlyEnabled {
   144  		q = q.Where("enabled = ?", true)
   145  	}
   146  
   147  	if err = q.Count(&total).Error; err != nil {
   148  		err = errors.Wrap(apperr.ErrTaskList, err.Error())
   149  		return
   150  	}
   151  
   152  	q = q.Preload("Triggers").
   153  		Preload("Triggers.Script").
   154  		Preload("Triggers.Entities").
   155  		Preload("Conditions").
   156  		Preload("Conditions.Script").
   157  		Preload("Actions").
   158  		Preload("Actions.Script").
   159  		Preload("Actions.Entity").
   160  		Preload("Area").
   161  		Limit(limit).
   162  		Offset(offset)
   163  
   164  	if sort != "" && orderBy != "" {
   165  		q = q.
   166  			Order(fmt.Sprintf("%s %s", sort, orderBy))
   167  	}
   168  
   169  	if err = q.Find(&list).Error; err != nil {
   170  		err = errors.Wrap(apperr.ErrTaskList, err.Error())
   171  	}
   172  	return
   173  }
   174  
   175  // Search ...
   176  func (n Tasks) Search(ctx context.Context, query string, limit, offset int) (list []*Task, total int64, err error) {
   177  
   178  	q := n.Db.WithContext(ctx).Model(&Task{}).
   179  		Where("name LIKE ?", "%"+query+"%")
   180  
   181  	if err = q.Count(&total).Error; err != nil {
   182  		err = errors.Wrap(apperr.ErrTaskSearch, err.Error())
   183  		return
   184  	}
   185  
   186  	q = q.
   187  		Limit(limit).
   188  		Offset(offset).
   189  		Order("name ASC")
   190  
   191  	list = make([]*Task, 0)
   192  	if err = q.Find(&list).Error; err != nil {
   193  		err = errors.Wrap(apperr.ErrTaskSearch, err.Error())
   194  	}
   195  	return
   196  }
   197  
   198  // DeleteTrigger ...
   199  func (n Tasks) DeleteTrigger(ctx context.Context, id int64) (err error) {
   200  	if err = n.Db.WithContext(ctx).Model(&Task{Id: id}).Association("Triggers").Clear(); err != nil {
   201  		err = errors.Wrap(apperr.ErrTaskDeleteTrigger, err.Error())
   202  	}
   203  	return
   204  }
   205  
   206  // DeleteCondition ...
   207  func (n Tasks) DeleteCondition(ctx context.Context, id int64) (err error) {
   208  	if err = n.Db.WithContext(ctx).Model(&Task{Id: id}).Association("Conditions").Clear(); err != nil {
   209  		err = errors.Wrap(apperr.ErrTaskDeleteCondition, err.Error())
   210  	}
   211  	return
   212  }
   213  
   214  // DeleteAction ...
   215  func (n Tasks) DeleteAction(ctx context.Context, id int64) (err error) {
   216  	if err = n.Db.WithContext(ctx).Model(&Task{Id: id}).Association("Actions").Clear(); err != nil {
   217  		err = errors.Wrap(apperr.ErrTaskDeleteAction, err.Error())
   218  	}
   219  	return
   220  }