diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..7d21478f --- /dev/null +++ b/.env.example @@ -0,0 +1,7 @@ +MARIADB_HOSTNAME=localhost +MARIADB_USERNAME=root +MARIADB_PASSWORD=password +MARIADB_DATABASE=jomon +MARIADB_PORT=3306 +IS_DEBUG_MODE=true +UPLOAD_DIR=./uploads diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000..551c68f6 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,95 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: + - v2 + pull_request: + branches: + - v2 + schedule: + - cron: '0 0 1 * *' + workflow_dispatch: + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: go + build-mode: autobuild + # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index cfdc62ec..ca657867 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -88,7 +88,7 @@ jobs: MARIADB_PORT: 50000 - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: files: ./coverage.out token: ${{ secrets.CODECOV_TOKEN }} diff --git a/Dockerfile b/Dockerfile index c494ba9d..dac10f7c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ ## build backend -FROM golang:1.23.2-alpine as server-build +FROM golang:1.23.3-alpine as server-build WORKDIR /github.com/traPtitech/Jomon COPY go.mod go.sum ./ diff --git a/Dockerfile.dev b/Dockerfile.dev index 763ddbec..7bddbd69 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -1,4 +1,4 @@ -FROM golang:1.23.2-alpine as build +FROM golang:1.23.3-alpine as build ENV CGO_ENABLED 0 ENV TZ Asia/Tokyo diff --git a/README.md b/README.md index 61bfceeb..a3e0ebee 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ make down ## Staging -1. Set .env file. +1. Set `.env` file. You can refer to `.env.example` as an example. - `IS_DEBUG_MODE`: Set `true` if you want to run the server in debug mode, otherwise do not set this variable. - `PORT`: Port number for Jomon staging server diff --git a/docs/swagger.yaml b/docs/swagger.yaml index fe1e2f9b..d29e7c52 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -153,6 +153,7 @@ paths: - $ref: "#/components/parameters/offsetQuery" - $ref: "#/components/parameters/tagQuery" - $ref: "#/components/parameters/groupQuery" + - $ref: "#/components/parameters/createdByQuery" responses: "200": description: 取得できた場合。該当するものがなくても空配列を返す。 @@ -1457,6 +1458,14 @@ components: in: query schema: type: string + createdByQuery: + name: created_by + description: 作成者 + required: false + in: query + schema: + type: string + format: uuid requestQuery: name: request description: 依頼 diff --git a/ent/migrate/schema.go b/ent/migrate/schema.go index c8c518f2..5def38e4 100644 --- a/ent/migrate/schema.go +++ b/ent/migrate/schema.go @@ -237,6 +237,7 @@ var ( // TransactionDetailsColumns holds the columns for the "transaction_details" table. TransactionDetailsColumns = []*schema.Column{ {Name: "id", Type: field.TypeUUID}, + {Name: "title", Type: field.TypeString, Size: 64}, {Name: "amount", Type: field.TypeInt, Default: 0}, {Name: "target", Type: field.TypeString, Default: ""}, {Name: "created_at", Type: field.TypeTime}, @@ -251,7 +252,7 @@ var ( ForeignKeys: []*schema.ForeignKey{ { Symbol: "transaction_details_transactions_detail", - Columns: []*schema.Column{TransactionDetailsColumns[5]}, + Columns: []*schema.Column{TransactionDetailsColumns[6]}, RefColumns: []*schema.Column{TransactionsColumns[0]}, OnDelete: schema.Cascade, }, diff --git a/ent/mutation.go b/ent/mutation.go index e19b834e..b330e835 100644 --- a/ent/mutation.go +++ b/ent/mutation.go @@ -6560,6 +6560,7 @@ type TransactionDetailMutation struct { op Op typ string id *uuid.UUID + title *string amount *int addamount *int target *string @@ -6677,6 +6678,42 @@ func (m *TransactionDetailMutation) IDs(ctx context.Context) ([]uuid.UUID, error } } +// SetTitle sets the "title" field. +func (m *TransactionDetailMutation) SetTitle(s string) { + m.title = &s +} + +// Title returns the value of the "title" field in the mutation. +func (m *TransactionDetailMutation) Title() (r string, exists bool) { + v := m.title + if v == nil { + return + } + return *v, true +} + +// OldTitle returns the old "title" field's value of the TransactionDetail entity. +// If the TransactionDetail object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *TransactionDetailMutation) OldTitle(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldTitle is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldTitle requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldTitle: %w", err) + } + return oldValue.Title, nil +} + +// ResetTitle resets all changes to the "title" field. +func (m *TransactionDetailMutation) ResetTitle() { + m.title = nil +} + // SetAmount sets the "amount" field. func (m *TransactionDetailMutation) SetAmount(i int) { m.amount = &i @@ -6914,7 +6951,10 @@ func (m *TransactionDetailMutation) Type() string { // order to get all numeric fields that were incremented/decremented, call // AddedFields(). func (m *TransactionDetailMutation) Fields() []string { - fields := make([]string, 0, 4) + fields := make([]string, 0, 5) + if m.title != nil { + fields = append(fields, transactiondetail.FieldTitle) + } if m.amount != nil { fields = append(fields, transactiondetail.FieldAmount) } @@ -6935,6 +6975,8 @@ func (m *TransactionDetailMutation) Fields() []string { // schema. func (m *TransactionDetailMutation) Field(name string) (ent.Value, bool) { switch name { + case transactiondetail.FieldTitle: + return m.Title() case transactiondetail.FieldAmount: return m.Amount() case transactiondetail.FieldTarget: @@ -6952,6 +6994,8 @@ func (m *TransactionDetailMutation) Field(name string) (ent.Value, bool) { // database failed. func (m *TransactionDetailMutation) OldField(ctx context.Context, name string) (ent.Value, error) { switch name { + case transactiondetail.FieldTitle: + return m.OldTitle(ctx) case transactiondetail.FieldAmount: return m.OldAmount(ctx) case transactiondetail.FieldTarget: @@ -6969,6 +7013,13 @@ func (m *TransactionDetailMutation) OldField(ctx context.Context, name string) ( // type. func (m *TransactionDetailMutation) SetField(name string, value ent.Value) error { switch name { + case transactiondetail.FieldTitle: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetTitle(v) + return nil case transactiondetail.FieldAmount: v, ok := value.(int) if !ok { @@ -7061,6 +7112,9 @@ func (m *TransactionDetailMutation) ClearField(name string) error { // It returns an error if the field is not defined in the schema. func (m *TransactionDetailMutation) ResetField(name string) error { switch name { + case transactiondetail.FieldTitle: + m.ResetTitle() + return nil case transactiondetail.FieldAmount: m.ResetAmount() return nil diff --git a/ent/runtime.go b/ent/runtime.go index 2a1993c7..7d8204e9 100644 --- a/ent/runtime.go +++ b/ent/runtime.go @@ -152,20 +152,39 @@ func init() { transaction.DefaultID = transactionDescID.Default.(func() uuid.UUID) transactiondetailFields := schema.TransactionDetail{}.Fields() _ = transactiondetailFields + // transactiondetailDescTitle is the schema descriptor for title field. + transactiondetailDescTitle := transactiondetailFields[1].Descriptor() + // transactiondetail.TitleValidator is a validator for the "title" field. It is called by the builders before save. + transactiondetail.TitleValidator = func() func(string) error { + validators := transactiondetailDescTitle.Validators + fns := [...]func(string) error{ + validators[0].(func(string) error), + validators[1].(func(string) error), + validators[2].(func(string) error), + } + return func(title string) error { + for _, fn := range fns { + if err := fn(title); err != nil { + return err + } + } + return nil + } + }() // transactiondetailDescAmount is the schema descriptor for amount field. - transactiondetailDescAmount := transactiondetailFields[1].Descriptor() + transactiondetailDescAmount := transactiondetailFields[2].Descriptor() // transactiondetail.DefaultAmount holds the default value on creation for the amount field. transactiondetail.DefaultAmount = transactiondetailDescAmount.Default.(int) // transactiondetailDescTarget is the schema descriptor for target field. - transactiondetailDescTarget := transactiondetailFields[2].Descriptor() + transactiondetailDescTarget := transactiondetailFields[3].Descriptor() // transactiondetail.DefaultTarget holds the default value on creation for the target field. transactiondetail.DefaultTarget = transactiondetailDescTarget.Default.(string) // transactiondetailDescCreatedAt is the schema descriptor for created_at field. - transactiondetailDescCreatedAt := transactiondetailFields[3].Descriptor() + transactiondetailDescCreatedAt := transactiondetailFields[4].Descriptor() // transactiondetail.DefaultCreatedAt holds the default value on creation for the created_at field. transactiondetail.DefaultCreatedAt = transactiondetailDescCreatedAt.Default.(func() time.Time) // transactiondetailDescUpdatedAt is the schema descriptor for updated_at field. - transactiondetailDescUpdatedAt := transactiondetailFields[4].Descriptor() + transactiondetailDescUpdatedAt := transactiondetailFields[5].Descriptor() // transactiondetail.DefaultUpdatedAt holds the default value on creation for the updated_at field. transactiondetail.DefaultUpdatedAt = transactiondetailDescUpdatedAt.Default.(func() time.Time) // transactiondetail.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. diff --git a/ent/runtime/runtime.go b/ent/runtime/runtime.go index f110b81d..7b16654b 100644 --- a/ent/runtime/runtime.go +++ b/ent/runtime/runtime.go @@ -5,6 +5,6 @@ package runtime // The schema-stitching logic is generated in github.com/traPtitech/Jomon/ent/runtime.go const ( - Version = "v0.14.0" // Version of ent codegen. - Sum = "h1:EO3Z9aZ5bXJatJeGqu/EVdnNr6K4mRq3rWe5owt0MC4=" // Sum of ent codegen. + Version = "v0.14.1" // Version of ent codegen. + Sum = "h1:fUERL506Pqr92EPHJqr8EYxbPioflJo6PudkrEA8a/s=" // Sum of ent codegen. ) diff --git a/ent/schema/transactiondetail.go b/ent/schema/transactiondetail.go index 04ac7667..118605f9 100644 --- a/ent/schema/transactiondetail.go +++ b/ent/schema/transactiondetail.go @@ -1,6 +1,8 @@ package schema import ( + "errors" + "strings" "time" "entgo.io/ent" @@ -19,6 +21,12 @@ func (TransactionDetail) Fields() []ent.Field { return []ent.Field{ field.UUID("id", uuid.UUID{}). Default(uuid.New), + field.String("title").NotEmpty().MaxLen(64).Validate(func(s string) error { + if strings.Contains(s, "\n") { + return errors.New("title cannot contain new line") + } + return nil + }), field.Int("amount"). Default(0), field.String("target"). diff --git a/ent/transactiondetail.go b/ent/transactiondetail.go index fe3095f2..9a210de3 100644 --- a/ent/transactiondetail.go +++ b/ent/transactiondetail.go @@ -19,6 +19,8 @@ type TransactionDetail struct { config `json:"-"` // ID of the ent. ID uuid.UUID `json:"id,omitempty"` + // Title holds the value of the "title" field. + Title string `json:"title,omitempty"` // Amount holds the value of the "amount" field. Amount int `json:"amount,omitempty"` // Target holds the value of the "target" field. @@ -61,7 +63,7 @@ func (*TransactionDetail) scanValues(columns []string) ([]any, error) { switch columns[i] { case transactiondetail.FieldAmount: values[i] = new(sql.NullInt64) - case transactiondetail.FieldTarget: + case transactiondetail.FieldTitle, transactiondetail.FieldTarget: values[i] = new(sql.NullString) case transactiondetail.FieldCreatedAt, transactiondetail.FieldUpdatedAt: values[i] = new(sql.NullTime) @@ -90,6 +92,12 @@ func (td *TransactionDetail) assignValues(columns []string, values []any) error } else if value != nil { td.ID = *value } + case transactiondetail.FieldTitle: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field title", values[i]) + } else if value.Valid { + td.Title = value.String + } case transactiondetail.FieldAmount: if value, ok := values[i].(*sql.NullInt64); !ok { return fmt.Errorf("unexpected type %T for field amount", values[i]) @@ -162,6 +170,9 @@ func (td *TransactionDetail) String() string { var builder strings.Builder builder.WriteString("TransactionDetail(") builder.WriteString(fmt.Sprintf("id=%v, ", td.ID)) + builder.WriteString("title=") + builder.WriteString(td.Title) + builder.WriteString(", ") builder.WriteString("amount=") builder.WriteString(fmt.Sprintf("%v", td.Amount)) builder.WriteString(", ") diff --git a/ent/transactiondetail/transactiondetail.go b/ent/transactiondetail/transactiondetail.go index 7929c68c..81db2aa5 100644 --- a/ent/transactiondetail/transactiondetail.go +++ b/ent/transactiondetail/transactiondetail.go @@ -15,6 +15,8 @@ const ( Label = "transaction_detail" // FieldID holds the string denoting the id field in the database. FieldID = "id" + // FieldTitle holds the string denoting the title field in the database. + FieldTitle = "title" // FieldAmount holds the string denoting the amount field in the database. FieldAmount = "amount" // FieldTarget holds the string denoting the target field in the database. @@ -39,6 +41,7 @@ const ( // Columns holds all SQL columns for transactiondetail fields. var Columns = []string{ FieldID, + FieldTitle, FieldAmount, FieldTarget, FieldCreatedAt, @@ -67,6 +70,8 @@ func ValidColumn(column string) bool { } var ( + // TitleValidator is a validator for the "title" field. It is called by the builders before save. + TitleValidator func(string) error // DefaultAmount holds the default value on creation for the "amount" field. DefaultAmount int // DefaultTarget holds the default value on creation for the "target" field. @@ -89,6 +94,11 @@ func ByID(opts ...sql.OrderTermOption) OrderOption { return sql.OrderByField(FieldID, opts...).ToFunc() } +// ByTitle orders the results by the title field. +func ByTitle(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldTitle, opts...).ToFunc() +} + // ByAmount orders the results by the amount field. func ByAmount(opts ...sql.OrderTermOption) OrderOption { return sql.OrderByField(FieldAmount, opts...).ToFunc() diff --git a/ent/transactiondetail/where.go b/ent/transactiondetail/where.go index 60d337fe..7f377c46 100644 --- a/ent/transactiondetail/where.go +++ b/ent/transactiondetail/where.go @@ -56,6 +56,11 @@ func IDLTE(id uuid.UUID) predicate.TransactionDetail { return predicate.TransactionDetail(sql.FieldLTE(FieldID, id)) } +// Title applies equality check predicate on the "title" field. It's identical to TitleEQ. +func Title(v string) predicate.TransactionDetail { + return predicate.TransactionDetail(sql.FieldEQ(FieldTitle, v)) +} + // Amount applies equality check predicate on the "amount" field. It's identical to AmountEQ. func Amount(v int) predicate.TransactionDetail { return predicate.TransactionDetail(sql.FieldEQ(FieldAmount, v)) @@ -76,6 +81,71 @@ func UpdatedAt(v time.Time) predicate.TransactionDetail { return predicate.TransactionDetail(sql.FieldEQ(FieldUpdatedAt, v)) } +// TitleEQ applies the EQ predicate on the "title" field. +func TitleEQ(v string) predicate.TransactionDetail { + return predicate.TransactionDetail(sql.FieldEQ(FieldTitle, v)) +} + +// TitleNEQ applies the NEQ predicate on the "title" field. +func TitleNEQ(v string) predicate.TransactionDetail { + return predicate.TransactionDetail(sql.FieldNEQ(FieldTitle, v)) +} + +// TitleIn applies the In predicate on the "title" field. +func TitleIn(vs ...string) predicate.TransactionDetail { + return predicate.TransactionDetail(sql.FieldIn(FieldTitle, vs...)) +} + +// TitleNotIn applies the NotIn predicate on the "title" field. +func TitleNotIn(vs ...string) predicate.TransactionDetail { + return predicate.TransactionDetail(sql.FieldNotIn(FieldTitle, vs...)) +} + +// TitleGT applies the GT predicate on the "title" field. +func TitleGT(v string) predicate.TransactionDetail { + return predicate.TransactionDetail(sql.FieldGT(FieldTitle, v)) +} + +// TitleGTE applies the GTE predicate on the "title" field. +func TitleGTE(v string) predicate.TransactionDetail { + return predicate.TransactionDetail(sql.FieldGTE(FieldTitle, v)) +} + +// TitleLT applies the LT predicate on the "title" field. +func TitleLT(v string) predicate.TransactionDetail { + return predicate.TransactionDetail(sql.FieldLT(FieldTitle, v)) +} + +// TitleLTE applies the LTE predicate on the "title" field. +func TitleLTE(v string) predicate.TransactionDetail { + return predicate.TransactionDetail(sql.FieldLTE(FieldTitle, v)) +} + +// TitleContains applies the Contains predicate on the "title" field. +func TitleContains(v string) predicate.TransactionDetail { + return predicate.TransactionDetail(sql.FieldContains(FieldTitle, v)) +} + +// TitleHasPrefix applies the HasPrefix predicate on the "title" field. +func TitleHasPrefix(v string) predicate.TransactionDetail { + return predicate.TransactionDetail(sql.FieldHasPrefix(FieldTitle, v)) +} + +// TitleHasSuffix applies the HasSuffix predicate on the "title" field. +func TitleHasSuffix(v string) predicate.TransactionDetail { + return predicate.TransactionDetail(sql.FieldHasSuffix(FieldTitle, v)) +} + +// TitleEqualFold applies the EqualFold predicate on the "title" field. +func TitleEqualFold(v string) predicate.TransactionDetail { + return predicate.TransactionDetail(sql.FieldEqualFold(FieldTitle, v)) +} + +// TitleContainsFold applies the ContainsFold predicate on the "title" field. +func TitleContainsFold(v string) predicate.TransactionDetail { + return predicate.TransactionDetail(sql.FieldContainsFold(FieldTitle, v)) +} + // AmountEQ applies the EQ predicate on the "amount" field. func AmountEQ(v int) predicate.TransactionDetail { return predicate.TransactionDetail(sql.FieldEQ(FieldAmount, v)) diff --git a/ent/transactiondetail_create.go b/ent/transactiondetail_create.go index 25cd01b6..b6aa5326 100644 --- a/ent/transactiondetail_create.go +++ b/ent/transactiondetail_create.go @@ -22,6 +22,12 @@ type TransactionDetailCreate struct { hooks []Hook } +// SetTitle sets the "title" field. +func (tdc *TransactionDetailCreate) SetTitle(s string) *TransactionDetailCreate { + tdc.mutation.SetTitle(s) + return tdc +} + // SetAmount sets the "amount" field. func (tdc *TransactionDetailCreate) SetAmount(i int) *TransactionDetailCreate { tdc.mutation.SetAmount(i) @@ -170,6 +176,14 @@ func (tdc *TransactionDetailCreate) defaults() { // check runs all checks and user-defined validators on the builder. func (tdc *TransactionDetailCreate) check() error { + if _, ok := tdc.mutation.Title(); !ok { + return &ValidationError{Name: "title", err: errors.New(`ent: missing required field "TransactionDetail.title"`)} + } + if v, ok := tdc.mutation.Title(); ok { + if err := transactiondetail.TitleValidator(v); err != nil { + return &ValidationError{Name: "title", err: fmt.Errorf(`ent: validator failed for field "TransactionDetail.title": %w`, err)} + } + } if _, ok := tdc.mutation.Amount(); !ok { return &ValidationError{Name: "amount", err: errors.New(`ent: missing required field "TransactionDetail.amount"`)} } @@ -217,6 +231,10 @@ func (tdc *TransactionDetailCreate) createSpec() (*TransactionDetail, *sqlgraph. _node.ID = id _spec.ID.Value = &id } + if value, ok := tdc.mutation.Title(); ok { + _spec.SetField(transactiondetail.FieldTitle, field.TypeString, value) + _node.Title = value + } if value, ok := tdc.mutation.Amount(); ok { _spec.SetField(transactiondetail.FieldAmount, field.TypeInt, value) _node.Amount = value diff --git a/ent/transactiondetail_query.go b/ent/transactiondetail_query.go index e2dfe2a9..b5d9539b 100644 --- a/ent/transactiondetail_query.go +++ b/ent/transactiondetail_query.go @@ -300,12 +300,12 @@ func (tdq *TransactionDetailQuery) WithTransaction(opts ...func(*TransactionQuer // Example: // // var v []struct { -// Amount int `json:"amount,omitempty"` +// Title string `json:"title,omitempty"` // Count int `json:"count,omitempty"` // } // // client.TransactionDetail.Query(). -// GroupBy(transactiondetail.FieldAmount). +// GroupBy(transactiondetail.FieldTitle). // Aggregate(ent.Count()). // Scan(ctx, &v) func (tdq *TransactionDetailQuery) GroupBy(field string, fields ...string) *TransactionDetailGroupBy { @@ -323,11 +323,11 @@ func (tdq *TransactionDetailQuery) GroupBy(field string, fields ...string) *Tran // Example: // // var v []struct { -// Amount int `json:"amount,omitempty"` +// Title string `json:"title,omitempty"` // } // // client.TransactionDetail.Query(). -// Select(transactiondetail.FieldAmount). +// Select(transactiondetail.FieldTitle). // Scan(ctx, &v) func (tdq *TransactionDetailQuery) Select(fields ...string) *TransactionDetailSelect { tdq.ctx.Fields = append(tdq.ctx.Fields, fields...) diff --git a/ent/transactiondetail_update.go b/ent/transactiondetail_update.go index 418fd1b9..81e609c8 100644 --- a/ent/transactiondetail_update.go +++ b/ent/transactiondetail_update.go @@ -30,6 +30,20 @@ func (tdu *TransactionDetailUpdate) Where(ps ...predicate.TransactionDetail) *Tr return tdu } +// SetTitle sets the "title" field. +func (tdu *TransactionDetailUpdate) SetTitle(s string) *TransactionDetailUpdate { + tdu.mutation.SetTitle(s) + return tdu +} + +// SetNillableTitle sets the "title" field if the given value is not nil. +func (tdu *TransactionDetailUpdate) SetNillableTitle(s *string) *TransactionDetailUpdate { + if s != nil { + tdu.SetTitle(*s) + } + return tdu +} + // SetAmount sets the "amount" field. func (tdu *TransactionDetailUpdate) SetAmount(i int) *TransactionDetailUpdate { tdu.mutation.ResetAmount() @@ -151,7 +165,20 @@ func (tdu *TransactionDetailUpdate) defaults() { } } +// check runs all checks and user-defined validators on the builder. +func (tdu *TransactionDetailUpdate) check() error { + if v, ok := tdu.mutation.Title(); ok { + if err := transactiondetail.TitleValidator(v); err != nil { + return &ValidationError{Name: "title", err: fmt.Errorf(`ent: validator failed for field "TransactionDetail.title": %w`, err)} + } + } + return nil +} + func (tdu *TransactionDetailUpdate) sqlSave(ctx context.Context) (n int, err error) { + if err := tdu.check(); err != nil { + return n, err + } _spec := sqlgraph.NewUpdateSpec(transactiondetail.Table, transactiondetail.Columns, sqlgraph.NewFieldSpec(transactiondetail.FieldID, field.TypeUUID)) if ps := tdu.mutation.predicates; len(ps) > 0 { _spec.Predicate = func(selector *sql.Selector) { @@ -160,6 +187,9 @@ func (tdu *TransactionDetailUpdate) sqlSave(ctx context.Context) (n int, err err } } } + if value, ok := tdu.mutation.Title(); ok { + _spec.SetField(transactiondetail.FieldTitle, field.TypeString, value) + } if value, ok := tdu.mutation.Amount(); ok { _spec.SetField(transactiondetail.FieldAmount, field.TypeInt, value) } @@ -224,6 +254,20 @@ type TransactionDetailUpdateOne struct { mutation *TransactionDetailMutation } +// SetTitle sets the "title" field. +func (tduo *TransactionDetailUpdateOne) SetTitle(s string) *TransactionDetailUpdateOne { + tduo.mutation.SetTitle(s) + return tduo +} + +// SetNillableTitle sets the "title" field if the given value is not nil. +func (tduo *TransactionDetailUpdateOne) SetNillableTitle(s *string) *TransactionDetailUpdateOne { + if s != nil { + tduo.SetTitle(*s) + } + return tduo +} + // SetAmount sets the "amount" field. func (tduo *TransactionDetailUpdateOne) SetAmount(i int) *TransactionDetailUpdateOne { tduo.mutation.ResetAmount() @@ -358,7 +402,20 @@ func (tduo *TransactionDetailUpdateOne) defaults() { } } +// check runs all checks and user-defined validators on the builder. +func (tduo *TransactionDetailUpdateOne) check() error { + if v, ok := tduo.mutation.Title(); ok { + if err := transactiondetail.TitleValidator(v); err != nil { + return &ValidationError{Name: "title", err: fmt.Errorf(`ent: validator failed for field "TransactionDetail.title": %w`, err)} + } + } + return nil +} + func (tduo *TransactionDetailUpdateOne) sqlSave(ctx context.Context) (_node *TransactionDetail, err error) { + if err := tduo.check(); err != nil { + return _node, err + } _spec := sqlgraph.NewUpdateSpec(transactiondetail.Table, transactiondetail.Columns, sqlgraph.NewFieldSpec(transactiondetail.FieldID, field.TypeUUID)) id, ok := tduo.mutation.ID() if !ok { @@ -384,6 +441,9 @@ func (tduo *TransactionDetailUpdateOne) sqlSave(ctx context.Context) (_node *Tra } } } + if value, ok := tduo.mutation.Title(); ok { + _spec.SetField(transactiondetail.FieldTitle, field.TypeString, value) + } if value, ok := tduo.mutation.Amount(); ok { _spec.SetField(transactiondetail.FieldAmount, field.TypeInt, value) } diff --git a/go.mod b/go.mod index 3b792d53..e8593852 100644 --- a/go.mod +++ b/go.mod @@ -1,33 +1,33 @@ module github.com/traPtitech/Jomon -go 1.23.0 +go 1.23.3 require ( - entgo.io/ent v0.14.0 + entgo.io/ent v0.14.1 github.com/go-sql-driver/mysql v1.8.1 github.com/google/uuid v1.6.0 github.com/gorilla/sessions v1.4.0 - github.com/labstack/echo-contrib v0.17.1 - github.com/labstack/echo/v4 v4.12.0 + github.com/labstack/echo-contrib v0.17.2 + github.com/labstack/echo/v4 v4.13.3 github.com/ncw/swift v1.0.53 github.com/samber/lo v1.47.0 - github.com/stretchr/testify v1.9.0 - go.uber.org/mock v0.4.0 + github.com/stretchr/testify v1.10.0 + go.uber.org/mock v0.5.0 go.uber.org/zap v1.27.0 ) require ( - ariga.io/atlas v0.19.1-0.20240203083654-5948b60a8e43 // indirect + ariga.io/atlas v0.29.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/agext/levenshtein v1.2.3 // indirect - github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect + github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect + github.com/bmatcuk/doublestar v1.3.4 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-openapi/inflect v0.19.0 // indirect - github.com/golang-jwt/jwt v3.2.2+incompatible // indirect + github.com/go-openapi/inflect v0.21.0 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/gorilla/context v1.1.2 // indirect github.com/gorilla/securecookie v1.1.2 // indirect - github.com/hashicorp/hcl/v2 v2.14.0 // indirect + github.com/hashicorp/hcl/v2 v2.23.0 // indirect github.com/labstack/gommon v0.4.2 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect @@ -35,13 +35,15 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect - github.com/zclconf/go-cty v1.11.0 // indirect - go.uber.org/multierr v1.10.0 // indirect - golang.org/x/crypto v0.22.0 // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.16.0 // indirect - golang.org/x/time v0.5.0 // indirect + github.com/zclconf/go-cty v1.15.1 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/crypto v0.31.0 // indirect + golang.org/x/mod v0.22.0 // indirect + golang.org/x/net v0.33.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect + golang.org/x/time v0.8.0 // indirect + golang.org/x/tools v0.28.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 6644a7e5..b1c7b640 100644 --- a/go.sum +++ b/go.sum @@ -1,25 +1,25 @@ -ariga.io/atlas v0.19.1-0.20240203083654-5948b60a8e43 h1:GwdJbXydHCYPedeeLt4x/lrlIISQ4JTH1mRWuE5ZZ14= -ariga.io/atlas v0.19.1-0.20240203083654-5948b60a8e43/go.mod h1:uj3pm+hUTVN/X5yfdBexHlZv+1Xu5u5ZbZx7+CDavNU= -entgo.io/ent v0.14.0 h1:EO3Z9aZ5bXJatJeGqu/EVdnNr6K4mRq3rWe5owt0MC4= -entgo.io/ent v0.14.0/go.mod h1:qCEmo+biw3ccBn9OyL4ZK5dfpwg++l1Gxwac5B1206A= +ariga.io/atlas v0.29.1 h1:7gB8XRFTnJeZ7ZiccNCJqwBtUv3yjFyxRFDMzu0AmRg= +ariga.io/atlas v0.29.1/go.mod h1:lkLAw/t2/P7g5CFYlYmHvNuShlmGujwm3OGsW00xowI= +entgo.io/ent v0.14.1 h1:fUERL506Pqr92EPHJqr8EYxbPioflJo6PudkrEA8a/s= +entgo.io/ent v0.14.1/go.mod h1:MH6XLG0KXpkcDQhKiHfANZSzR55TJyPL5IGNpI8wpco= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= -github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= -github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= +github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= +github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= +github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0= +github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4= -github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4= +github.com/go-openapi/inflect v0.21.0 h1:FoBjBTQEcbg2cJUWX6uwL9OyIW8eqc9k4KhN4lfbeYk= +github.com/go-openapi/inflect v0.21.0/go.mod h1:INezMuUu7SJQc2AyR3WO0DqqYUJSj8Kb4hBd7WtjlAw= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= -github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= @@ -32,18 +32,12 @@ github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kX github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ= github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik= -github.com/hashicorp/hcl/v2 v2.14.0 h1:jX6+Q38Ly9zaAJlAjnFVyeNSNCKKW8D0wvyg7vij5Wc= -github.com/hashicorp/hcl/v2 v2.14.0/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/labstack/echo-contrib v0.17.1 h1:7I/he7ylVKsDUieaGRZ9XxxTYOjfQwVzHzUYrNykfCU= -github.com/labstack/echo-contrib v0.17.1/go.mod h1:SnsCZtwHBAZm5uBSAtQtXQHI3wqEA73hvTn0bYMKnZA= -github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0= -github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM= +github.com/hashicorp/hcl/v2 v2.23.0 h1:Fphj1/gCylPxHutVSEOf2fBOh1VE4AuLV7+kbJf3qos= +github.com/hashicorp/hcl/v2 v2.23.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA= +github.com/labstack/echo-contrib v0.17.2 h1:K1zivqmtcC70X9VdBFdLomjPDEVHlrcAObqmuFj1c6w= +github.com/labstack/echo-contrib v0.17.2/go.mod h1:NeDh3PX7j/u+jR4iuDt1zHmWZSCz9c/p9mxXcDpyS8E= +github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY= +github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g= github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -65,46 +59,42 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc= github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU= -github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/zclconf/go-cty v1.11.0 h1:726SxLdi2SDnjY+BStqB9J1hNp4+2WlzyXLuimibIe0= -github.com/zclconf/go-cty v1.11.0/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA= +github.com/zclconf/go-cty v1.15.1 h1:RgQYm4j2EvoBRXOPxhUvxPzRrGDo1eCOhHXuGfrj5S0= +github.com/zclconf/go-cty v1.15.1/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= -go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= -go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= -go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= +go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= -golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= +golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= +golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/logging/http.go b/logging/http.go deleted file mode 100644 index e9d8bc2f..00000000 --- a/logging/http.go +++ /dev/null @@ -1,35 +0,0 @@ -package logging - -import "go.uber.org/zap/zapcore" - -type HTTPPayload struct { - RequestMethod string `json:"requestMethod"` - RequestURL string `json:"requestUrl"` - RequestSize string `json:"requestSize"` - Status int `json:"status"` - ResponseSize string `json:"responseSize"` - UserAgent string `json:"userAgent"` - RemoteIP string `json:"remoteIp"` - ServerIP string `json:"serverIp"` - Referer string `json:"referer"` - Latency string `json:"latency"` - Protocol string `json:"protocol"` - Error string `json:"error"` -} - -// MarshalLogObject implements zapcore.ObjectMarshaller interface. -func (p HTTPPayload) MarshalLogObject(enc zapcore.ObjectEncoder) error { - enc.AddString("requestMethod", p.RequestMethod) - enc.AddString("requestUrl", p.RequestURL) - enc.AddString("requestSize", p.RequestSize) - enc.AddInt("status", p.Status) - enc.AddString("responseSize", p.ResponseSize) - enc.AddString("userAgent", p.UserAgent) - enc.AddString("remoteIp", p.RemoteIP) - enc.AddString("serverIp", p.ServerIP) - enc.AddString("referer", p.Referer) - enc.AddString("latency", p.Latency) - enc.AddString("protocol", p.Protocol) - enc.AddString("error", p.Error) - return nil -} diff --git a/model/mock_model/mock_transaction.go b/model/mock_model/mock_transaction.go index 8ed24d71..abeb5f96 100644 --- a/model/mock_model/mock_transaction.go +++ b/model/mock_model/mock_transaction.go @@ -42,18 +42,18 @@ func (m *MockTransactionRepository) EXPECT() *MockTransactionRepositoryMockRecor } // CreateTransaction mocks base method. -func (m *MockTransactionRepository) CreateTransaction(ctx context.Context, Amount int, Target string, tags []*uuid.UUID, group, requestID *uuid.UUID) (*model.TransactionResponse, error) { +func (m *MockTransactionRepository) CreateTransaction(ctx context.Context, title string, Amount int, Target string, tags []*uuid.UUID, group, requestID *uuid.UUID) (*model.TransactionResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateTransaction", ctx, Amount, Target, tags, group, requestID) + ret := m.ctrl.Call(m, "CreateTransaction", ctx, title, Amount, Target, tags, group, requestID) ret0, _ := ret[0].(*model.TransactionResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // CreateTransaction indicates an expected call of CreateTransaction. -func (mr *MockTransactionRepositoryMockRecorder) CreateTransaction(ctx, Amount, Target, tags, group, requestID any) *gomock.Call { +func (mr *MockTransactionRepositoryMockRecorder) CreateTransaction(ctx, title, Amount, Target, tags, group, requestID any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateTransaction", reflect.TypeOf((*MockTransactionRepository)(nil).CreateTransaction), ctx, Amount, Target, tags, group, requestID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateTransaction", reflect.TypeOf((*MockTransactionRepository)(nil).CreateTransaction), ctx, title, Amount, Target, tags, group, requestID) } // GetTransaction mocks base method. @@ -87,16 +87,16 @@ func (mr *MockTransactionRepositoryMockRecorder) GetTransactions(ctx, query any) } // UpdateTransaction mocks base method. -func (m *MockTransactionRepository) UpdateTransaction(ctx context.Context, transactionID uuid.UUID, Amount int, Target string, tags []*uuid.UUID, group, requestID *uuid.UUID) (*model.TransactionResponse, error) { +func (m *MockTransactionRepository) UpdateTransaction(ctx context.Context, transactionID uuid.UUID, title string, Amount int, Target string, tags []*uuid.UUID, group, requestID *uuid.UUID) (*model.TransactionResponse, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateTransaction", ctx, transactionID, Amount, Target, tags, group, requestID) + ret := m.ctrl.Call(m, "UpdateTransaction", ctx, transactionID, title, Amount, Target, tags, group, requestID) ret0, _ := ret[0].(*model.TransactionResponse) ret1, _ := ret[1].(error) return ret0, ret1 } // UpdateTransaction indicates an expected call of UpdateTransaction. -func (mr *MockTransactionRepositoryMockRecorder) UpdateTransaction(ctx, transactionID, Amount, Target, tags, group, requestID any) *gomock.Call { +func (mr *MockTransactionRepositoryMockRecorder) UpdateTransaction(ctx, transactionID, title, Amount, Target, tags, group, requestID any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTransaction", reflect.TypeOf((*MockTransactionRepository)(nil).UpdateTransaction), ctx, transactionID, Amount, Target, tags, group, requestID) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTransaction", reflect.TypeOf((*MockTransactionRepository)(nil).UpdateTransaction), ctx, transactionID, title, Amount, Target, tags, group, requestID) } diff --git a/model/request_impl.go b/model/request_impl.go index c4ed15d9..9efc5174 100644 --- a/model/request_impl.go +++ b/model/request_impl.go @@ -112,6 +112,14 @@ func (repo *EntRepository) GetRequests( ), ) } + if query.CreatedBy != nil && *query.CreatedBy != uuid.Nil { + requestsq = requestsq. + Where( + request.HasUserWith( + user.IDEQ(*query.CreatedBy), + ), + ) + } requests, err := requestsq.All(ctx) if err != nil { diff --git a/model/request_impl_test.go b/model/request_impl_test.go index 91fa8bcf..a690f7b7 100644 --- a/model/request_impl_test.go +++ b/model/request_impl_test.go @@ -37,6 +37,9 @@ func TestEntRepository_GetRequests(t *testing.T) { client8, storage8, err := setup(t, ctx, "get_requests8") require.NoError(t, err) repo8 := NewEntRepository(client8, storage8) + client9, storage9, err := setup(t, ctx, "get_requests9") + require.NoError(t, err) + repo9 := NewEntRepository(client9, storage9) t.Run("SuccessWithSortCreatedAt", func(t *testing.T) { t.Parallel() @@ -591,6 +594,85 @@ func TestEntRepository_GetRequests(t *testing.T) { assert.Equal(t, got[0].Tags[0].Name, request1.Tags[0].Name) } }) + + t.Run("SuccessWithQueryCreatedBy", func(t *testing.T) { + t.Parallel() + ctx := context.Background() + user1, err := repo9.CreateUser( + ctx, + random.AlphaNumeric(t, 20), + random.AlphaNumeric(t, 30), + true) + require.NoError(t, err) + user2, err := repo9.CreateUser( + ctx, + random.AlphaNumeric(t, 20), + random.AlphaNumeric(t, 30), + true) + require.NoError(t, err) + target := &RequestTarget{ + Target: user1.ID, + Amount: random.Numeric(t, 10000), + } + + budget := random.Numeric(t, 10000) + group, err := repo9.CreateGroup( + ctx, + random.AlphaNumeric(t, 20), + random.AlphaNumeric(t, 30), + &budget) + require.NoError(t, err) + + request1, err := repo9.CreateRequest( + ctx, + random.AlphaNumeric(t, 40), + random.AlphaNumeric(t, 100), + []*Tag{}, + []*RequestTarget{target}, + group, + user1.ID) + require.NoError(t, err) + _, err = repo9.CreateRequest( + ctx, + random.AlphaNumeric(t, 40), + random.AlphaNumeric(t, 100), + []*Tag{}, + []*RequestTarget{target}, + group, + user2.ID) + require.NoError(t, err) + + got, err := repo9.GetRequests(ctx, RequestQuery{ + CreatedBy: &user1.ID, + }) + require.NoError(t, err) + if assert.Len(t, got, 1) { + got := got[0] + exp := &RequestResponse{ + ID: request1.ID, + Status: request1.Status, + // FIXME: time.Time の内部表現が異なるため、比較ができない + CreatedAt: got.CreatedAt, + UpdatedAt: got.UpdatedAt, + CreatedBy: request1.CreatedBy, + Title: request1.Title, + Content: request1.Content, + Tags: request1.Tags, + // Targets: request1.Targets, + // Statuses: request1.Statuses, + Group: &Group{ + ID: request1.Group.ID, + Name: request1.Group.Name, + Description: request1.Group.Description, + Budget: request1.Group.Budget, + CreatedAt: got.Group.CreatedAt, + UpdatedAt: got.Group.UpdatedAt, + DeletedAt: request1.Group.DeletedAt, + }, + } + require.Equal(t, exp, got) + } + }) } func TestEntRepository_CreateRequest(t *testing.T) { diff --git a/model/transaction.go b/model/transaction.go index 43c9c3ba..a36feb5a 100644 --- a/model/transaction.go +++ b/model/transaction.go @@ -11,12 +11,12 @@ import ( type TransactionRepository interface { GetTransactions(ctx context.Context, query TransactionQuery) ([]*TransactionResponse, error) CreateTransaction( - ctx context.Context, Amount int, Target string, + ctx context.Context, title string, Amount int, Target string, tags []*uuid.UUID, group *uuid.UUID, requestID *uuid.UUID, ) (*TransactionResponse, error) GetTransaction(ctx context.Context, transactionID uuid.UUID) (*TransactionResponse, error) UpdateTransaction( - ctx context.Context, transactionID uuid.UUID, Amount int, Target string, + ctx context.Context, transactionID uuid.UUID, title string, Amount int, Target string, tags []*uuid.UUID, group *uuid.UUID, requestID *uuid.UUID, ) (*TransactionResponse, error) } @@ -28,6 +28,7 @@ type Transaction struct { type TransactionResponse struct { ID uuid.UUID + Title string Amount int Target string Request *uuid.UUID diff --git a/model/transaction_detail.go b/model/transaction_detail.go index dbd456ba..dfee3bfd 100644 --- a/model/transaction_detail.go +++ b/model/transaction_detail.go @@ -12,6 +12,7 @@ type TransactionDetailRepository interface { type TransactionDetail struct { ID uuid.UUID + Title string Amount int Target string CreatedAt time.Time diff --git a/model/transaction_detail_impl.go b/model/transaction_detail_impl.go index 2b611089..168f0751 100644 --- a/model/transaction_detail_impl.go +++ b/model/transaction_detail_impl.go @@ -10,9 +10,10 @@ import ( ) func (repo *EntRepository) createTransactionDetail( - ctx context.Context, tx *ent.Tx, amount int, target string, + ctx context.Context, tx *ent.Tx, title string, amount int, target string, ) (*TransactionDetail, error) { enttd, err := tx.Client().TransactionDetail.Create(). + SetTitle(title). SetAmount(amount). SetTarget(target). Save(ctx) @@ -23,7 +24,8 @@ func (repo *EntRepository) createTransactionDetail( } func (repo *EntRepository) updateTransactionDetail( - ctx context.Context, tx *ent.Tx, transactionID uuid.UUID, amount int, target string, + ctx context.Context, tx *ent.Tx, transactionID uuid.UUID, + title string, amount int, target string, ) (*TransactionDetail, error) { _, err := tx.Client().TransactionDetail.Update(). Where(transactiondetail.HasTransactionWith( @@ -35,6 +37,7 @@ func (repo *EntRepository) updateTransactionDetail( return nil, err } enttd, err := tx.Client().TransactionDetail.Create(). + SetTitle(title). SetAmount(amount). SetTarget(target). SetTransactionID(transactionID). @@ -53,6 +56,7 @@ func convertEntTransactionDetailToModelTransactionDetail( } return &TransactionDetail{ ID: enttd.ID, + Title: enttd.Title, Amount: enttd.Amount, Target: enttd.Target, CreatedAt: enttd.CreatedAt, diff --git a/model/transaction_detail_impl_test.go b/model/transaction_detail_impl_test.go index 427aa50c..046f6883 100644 --- a/model/transaction_detail_impl_test.go +++ b/model/transaction_detail_impl_test.go @@ -27,10 +27,11 @@ func TestEntRepository_createTransactionDetail(t *testing.T) { } }() + title := random.AlphaNumeric(t, 20) amount := random.Numeric(t, 100000) target := random.AlphaNumeric(t, 10) // Create TransactionDetail - td, err := repo.createTransactionDetail(ctx, tx, amount, target) + td, err := repo.createTransactionDetail(ctx, tx, title, amount, target) assert.NoError(t, err) err = tx.Commit() assert.NoError(t, err) @@ -58,17 +59,21 @@ func TestEntRepository_updateTransactionDetail(t *testing.T) { } }() + title := "Hoge" amount := 100 target := "hoge" // Create Transaction - trns, err := repo.CreateTransaction(ctx, amount, target, nil, nil, nil) + trns, err := repo.CreateTransaction(ctx, title, amount, target, nil, nil, nil) require.NoError(t, err) // Update TransactionDetail + updateTitle := "Fuga" updatedAmount := 1000 updatedTarget := "fuga" - td, err := repo.updateTransactionDetail(ctx, tx, trns.ID, updatedAmount, updatedTarget) + td, err := repo.updateTransactionDetail( + ctx, tx, trns.ID, + updateTitle, updatedAmount, updatedTarget) assert.NoError(t, err) err = tx.Commit() assert.NoError(t, err) diff --git a/model/transaction_impl.go b/model/transaction_impl.go index a7b88b8e..af7b5745 100644 --- a/model/transaction_impl.go +++ b/model/transaction_impl.go @@ -147,7 +147,7 @@ func (repo *EntRepository) GetTransaction( } func (repo *EntRepository) CreateTransaction( - ctx context.Context, amount int, target string, + ctx context.Context, title string, amount int, target string, tags []*uuid.UUID, groupID *uuid.UUID, requestID *uuid.UUID, ) (*TransactionResponse, error) { tx, err := repo.client.Tx(ctx) @@ -167,7 +167,7 @@ func (repo *EntRepository) CreateTransaction( }) // Create Transaction Detail - detail, err := repo.createTransactionDetail(ctx, tx, amount, target) + detail, err := repo.createTransactionDetail(ctx, tx, title, amount, target) if err != nil { err = RollbackWithError(tx, err) return nil, err @@ -248,7 +248,7 @@ func (repo *EntRepository) CreateTransaction( } func (repo *EntRepository) UpdateTransaction( - ctx context.Context, transactionID uuid.UUID, amount int, target string, + ctx context.Context, transactionID uuid.UUID, title string, amount int, target string, tags []*uuid.UUID, groupID *uuid.UUID, requestID *uuid.UUID, ) (*TransactionResponse, error) { tx, err := repo.client.Tx(ctx) @@ -263,7 +263,7 @@ func (repo *EntRepository) UpdateTransaction( }() // Update transaction Detail - _, err = repo.updateTransactionDetail(ctx, tx, transactionID, amount, target) + _, err = repo.updateTransactionDetail(ctx, tx, transactionID, title, amount, target) if err != nil { err = RollbackWithError(tx, err) return nil, err @@ -392,6 +392,7 @@ func ConvertEntTransactionToModelTransactionResponse( } return &TransactionResponse{ ID: transaction.ID, + Title: transaction.Edges.Detail.Title, Amount: transaction.Edges.Detail.Amount, Target: transaction.Edges.Detail.Target, Request: r, diff --git a/model/transaction_impl_test.go b/model/transaction_impl_test.go index b97d9c2b..a69f9444 100644 --- a/model/transaction_impl_test.go +++ b/model/transaction_impl_test.go @@ -59,6 +59,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { require.NoError(t, err) // Create Transactions + title := random.AlphaNumeric(t, 20) amount := random.Numeric(t, 100000) target := random.AlphaNumeric(t, 20) request, err := repo.CreateRequest( @@ -69,10 +70,10 @@ func TestEntRepository_GetTransactions(t *testing.T) { nil, user.ID) require.NoError(t, err) - tx1, err := repo.CreateTransaction(ctx, amount, target, nil, nil, &request.ID) + tx1, err := repo.CreateTransaction(ctx, title, amount, target, nil, nil, &request.ID) require.NoError(t, err) time.Sleep(1 * time.Second) - tx2, err := repo.CreateTransaction(ctx, amount, target, nil, nil, &request.ID) + tx2, err := repo.CreateTransaction(ctx, title, amount, target, nil, nil, &request.ID) require.NoError(t, err) // Get Transactions @@ -84,6 +85,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { assert.NoError(t, err) if assert.Len(t, got, 2) { assert.Equal(t, tx1.ID, got[1].ID) + assert.Equal(t, tx1.Title, got[1].Title) assert.Equal(t, tx1.Amount, got[1].Amount) assert.Equal(t, tx1.Target, got[1].Target) assert.Equal(t, tx1.CreatedAt, got[1].CreatedAt) @@ -108,6 +110,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { require.NoError(t, err) // Create Transactions + title := random.AlphaNumeric(t, 20) amount := random.Numeric(t, 100000) target := random.AlphaNumeric(t, 20) request, err := repo2.CreateRequest( @@ -118,10 +121,10 @@ func TestEntRepository_GetTransactions(t *testing.T) { nil, user.ID) require.NoError(t, err) - tx1, err := repo2.CreateTransaction(ctx, amount, target, nil, nil, &request.ID) + tx1, err := repo2.CreateTransaction(ctx, title, amount, target, nil, nil, &request.ID) require.NoError(t, err) time.Sleep(1 * time.Second) - tx2, err := repo2.CreateTransaction(ctx, amount, target, nil, nil, &request.ID) + tx2, err := repo2.CreateTransaction(ctx, title, amount, target, nil, nil, &request.ID) require.NoError(t, err) // Get Transactions @@ -133,6 +136,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { assert.NoError(t, err) if assert.Len(t, got, 2) { assert.Equal(t, tx1.ID, got[0].ID) + assert.Equal(t, tx1.Title, got[0].Title) assert.Equal(t, tx1.Amount, got[0].Amount) assert.Equal(t, tx1.Target, got[0].Target) assert.Equal(t, tx1.CreatedAt, got[0].CreatedAt) @@ -157,6 +161,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { require.NoError(t, err) // Create Transactions + title := random.AlphaNumeric(t, 20) target := random.AlphaNumeric(t, 20) request, err := repo3.CreateRequest( ctx, @@ -166,10 +171,10 @@ func TestEntRepository_GetTransactions(t *testing.T) { nil, user.ID) require.NoError(t, err) - tx1, err := repo3.CreateTransaction(ctx, 100, target, nil, nil, &request.ID) + tx1, err := repo3.CreateTransaction(ctx, title, 100, target, nil, nil, &request.ID) require.NoError(t, err) time.Sleep(1 * time.Second) - tx2, err := repo3.CreateTransaction(ctx, 10000, target, nil, nil, &request.ID) + tx2, err := repo3.CreateTransaction(ctx, title, 10000, target, nil, nil, &request.ID) require.NoError(t, err) // Get Transactions @@ -181,6 +186,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { assert.NoError(t, err) if assert.Len(t, got, 2) { assert.Equal(t, tx1.ID, got[0].ID) + assert.Equal(t, tx1.Title, got[0].Title) assert.Equal(t, tx1.Amount, got[0].Amount) assert.Equal(t, tx1.Target, got[0].Target) assert.Equal(t, tx1.CreatedAt, got[0].CreatedAt) @@ -208,6 +214,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { require.NoError(t, err) // Create Transactions + title := random.AlphaNumeric(t, 20) target := random.AlphaNumeric(t, 20) // nolint:contextcheck request, err := repo4.CreateRequest( @@ -219,11 +226,11 @@ func TestEntRepository_GetTransactions(t *testing.T) { require.NoError(t, err) // nolint:contextcheck - tx1, err := repo4.CreateTransaction(ctx, 100, target, nil, nil, &request.ID) + tx1, err := repo4.CreateTransaction(ctx, title, 100, target, nil, nil, &request.ID) require.NoError(t, err) time.Sleep(1 * time.Second) // nolint:contextcheck - tx2, err := repo4.CreateTransaction(ctx, 10000, target, nil, nil, &request.ID) + tx2, err := repo4.CreateTransaction(ctx, title, 10000, target, nil, nil, &request.ID) require.NoError(t, err) // Get Transactions @@ -236,6 +243,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { assert.NoError(t, err) if assert.Len(t, got, 2) { assert.Equal(t, tx2.ID, got[0].ID) + assert.Equal(t, tx2.Title, got[0].Title) assert.Equal(t, tx2.Amount, got[0].Amount) assert.Equal(t, tx2.Target, got[0].Target) assert.Equal(t, tx2.CreatedAt, got[0].CreatedAt) @@ -260,6 +268,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { require.NoError(t, err) // Create Transactions + title := random.AlphaNumeric(t, 20) amount := random.Numeric(t, 100000) target := random.AlphaNumeric(t, 20) request, err := repo5.CreateRequest( @@ -270,10 +279,10 @@ func TestEntRepository_GetTransactions(t *testing.T) { nil, user.ID) require.NoError(t, err) - tx1, err := repo5.CreateTransaction(ctx, amount, target, nil, nil, &request.ID) + tx1, err := repo5.CreateTransaction(ctx, title, amount, target, nil, nil, &request.ID) require.NoError(t, err) time.Sleep(1 * time.Second) - tx2, err := repo5.CreateTransaction(ctx, amount, target, nil, nil, &request.ID) + tx2, err := repo5.CreateTransaction(ctx, title, amount, target, nil, nil, &request.ID) require.NoError(t, err) // Get Transactions @@ -285,6 +294,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { assert.NoError(t, err) if assert.Len(t, got, 2) { assert.Equal(t, tx1.ID, got[1].ID) + assert.Equal(t, tx1.Title, got[1].Title) assert.Equal(t, tx1.Amount, got[1].Amount) assert.Equal(t, tx1.Target, got[1].Target) assert.Equal(t, tx1.CreatedAt, got[1].CreatedAt) @@ -309,6 +319,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { require.NoError(t, err) // Create Transactions + title := random.AlphaNumeric(t, 20) amount := random.Numeric(t, 100000) target1 := random.AlphaNumeric(t, 20) target2 := random.AlphaNumeric(t, 20) @@ -320,9 +331,9 @@ func TestEntRepository_GetTransactions(t *testing.T) { nil, user.ID) require.NoError(t, err) - tx, err := repo6.CreateTransaction(ctx, amount, target1, nil, nil, &request.ID) + tx, err := repo6.CreateTransaction(ctx, title, amount, target1, nil, nil, &request.ID) require.NoError(t, err) - _, err = repo6.CreateTransaction(ctx, amount, target2, nil, nil, &request.ID) + _, err = repo6.CreateTransaction(ctx, title, amount, target2, nil, nil, &request.ID) require.NoError(t, err) // Get Transactions @@ -333,6 +344,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { assert.NoError(t, err) if assert.Len(t, got, 1) { assert.Equal(t, tx.ID, got[0].ID) + assert.Equal(t, tx.Title, got[0].Title) assert.Equal(t, tx.Amount, got[0].Amount) assert.Equal(t, tx.Target, got[0].Target) assert.Equal(t, tx.CreatedAt, got[0].CreatedAt) @@ -352,6 +364,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { require.NoError(t, err) // Create Transactions + title := random.AlphaNumeric(t, 20) amount := random.Numeric(t, 100000) target := random.AlphaNumeric(t, 20) request, err := repo7.CreateRequest( @@ -362,7 +375,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { nil, user.ID) require.NoError(t, err) - _, err = repo7.CreateTransaction(ctx, amount, target, nil, nil, &request.ID) + _, err = repo7.CreateTransaction(ctx, title, amount, target, nil, nil, &request.ID) require.NoError(t, err) // Get Transactions @@ -374,7 +387,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { } time.Sleep(1 * time.Second) - tx, err := repo7.CreateTransaction(ctx, amount, target, nil, nil, &request.ID) + tx, err := repo7.CreateTransaction(ctx, title, amount, target, nil, nil, &request.ID) require.NoError(t, err) got, err := repo7.GetTransactions(ctx, query) @@ -400,6 +413,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { require.NoError(t, err) // Create Transactions + title := random.AlphaNumeric(t, 20) amount := random.Numeric(t, 100000) target := random.AlphaNumeric(t, 20) tag, err := repo8.CreateTag(ctx, random.AlphaNumeric(t, 20)) @@ -412,7 +426,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { nil, user.ID) require.NoError(t, err) - _, err = repo8.CreateTransaction(ctx, amount, target, nil, nil, &request.ID) + _, err = repo8.CreateTransaction(ctx, title, amount, target, nil, nil, &request.ID) require.NoError(t, err) // Get Transactions @@ -422,7 +436,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { tx, err := repo8.CreateTransaction( ctx, - amount, target, + title, amount, target, []*uuid.UUID{&tag.ID}, nil, &request.ID) require.NoError(t, err) @@ -430,6 +444,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { assert.NoError(t, err) if assert.Len(t, got, 1) { assert.Equal(t, tx.ID, got[0].ID) + assert.Equal(t, tx.Title, got[0].Title) assert.Equal(t, tx.Amount, got[0].Amount) assert.Equal(t, tx.Target, got[0].Target) assert.Equal(t, tx.CreatedAt, got[0].CreatedAt) @@ -449,6 +464,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { require.NoError(t, err) // Create Transactions + title := random.AlphaNumeric(t, 20) amount := random.Numeric(t, 100000) target := random.AlphaNumeric(t, 20) budget := random.Numeric(t, 100000) @@ -466,7 +482,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { nil, user.ID) require.NoError(t, err) - _, err = repo9.CreateTransaction(ctx, amount, target, nil, nil, &request.ID) + _, err = repo9.CreateTransaction(ctx, title, amount, target, nil, nil, &request.ID) require.NoError(t, err) // Get Transactions @@ -474,13 +490,14 @@ func TestEntRepository_GetTransactions(t *testing.T) { Group: &group.Name, } - tx, err := repo9.CreateTransaction(ctx, amount, target, nil, &group.ID, &request.ID) + tx, err := repo9.CreateTransaction(ctx, title, amount, target, nil, &group.ID, &request.ID) require.NoError(t, err) got, err := repo9.GetTransactions(ctx, query) assert.NoError(t, err) if assert.Len(t, got, 1) { assert.Equal(t, tx.ID, got[0].ID) + assert.Equal(t, tx.Title, got[0].Title) assert.Equal(t, tx.Amount, got[0].Amount) assert.Equal(t, tx.Target, got[0].Target) assert.Equal(t, tx.CreatedAt, got[0].CreatedAt) @@ -500,6 +517,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { require.NoError(t, err) // Create Transactions + title := random.AlphaNumeric(t, 20) amount := random.Numeric(t, 100000) target := random.AlphaNumeric(t, 20) request, err := repo10.CreateRequest( @@ -510,7 +528,7 @@ func TestEntRepository_GetTransactions(t *testing.T) { nil, user.ID) require.NoError(t, err) - _, err = repo10.CreateTransaction(ctx, amount, target, nil, nil, nil) + _, err = repo10.CreateTransaction(ctx, title, amount, target, nil, nil, nil) require.NoError(t, err) // Get Transactions @@ -518,13 +536,14 @@ func TestEntRepository_GetTransactions(t *testing.T) { Request: &request.ID, } - tx, err := repo10.CreateTransaction(ctx, amount, target, nil, nil, &request.ID) + tx, err := repo10.CreateTransaction(ctx, title, amount, target, nil, nil, &request.ID) require.NoError(t, err) got, err := repo10.GetTransactions(ctx, query) assert.NoError(t, err) if assert.Len(t, got, 1) { assert.Equal(t, tx.ID, got[0].ID) + assert.Equal(t, tx.Title, got[0].Title) assert.Equal(t, tx.Amount, got[0].Amount) assert.Equal(t, tx.Target, got[0].Target) assert.Equal(t, tx.CreatedAt, got[0].CreatedAt) @@ -561,6 +580,7 @@ func TestEntRepository_GetTransaction(t *testing.T) { require.NoError(t, err) // Create Transactions + title := random.AlphaNumeric(t, 20) amount := random.Numeric(t, 100000) target := random.AlphaNumeric(t, 20) _, err = repo.CreateRequest( @@ -571,7 +591,7 @@ func TestEntRepository_GetTransaction(t *testing.T) { nil, user.ID) require.NoError(t, err) - tx, err := repo.CreateTransaction(ctx, amount, target, nil, nil, nil) + tx, err := repo.CreateTransaction(ctx, title, amount, target, nil, nil, nil) require.NoError(t, err) // Get Transaction @@ -579,6 +599,7 @@ func TestEntRepository_GetTransaction(t *testing.T) { assert.NoError(t, err) if assert.NotNil(t, got) { assert.Equal(t, tx.ID, got.ID) + assert.Equal(t, tx.Title, got.Title) assert.Equal(t, tx.Amount, got.Amount) assert.Equal(t, tx.Target, got.Target) assert.Equal(t, tx.CreatedAt, got.CreatedAt) @@ -620,6 +641,7 @@ func TestEntRepository_CreateTransaction(t *testing.T) { require.NoError(t, err) // Create Transactions + title := random.AlphaNumeric(t, 20) target := random.AlphaNumeric(t, 20) request, err := repo.CreateRequest( ctx, @@ -631,10 +653,11 @@ func TestEntRepository_CreateTransaction(t *testing.T) { tx, err := repo.CreateTransaction( ctx, - amount, target, + title, amount, target, []*uuid.UUID{&tag.ID}, &group.ID, &request.ID) assert.NoError(t, err) if assert.NotNil(t, tx) { + assert.Equal(t, title, tx.Title) assert.Equal(t, amount, tx.Amount) assert.Equal(t, target, tx.Target) if assert.Len(t, tx.Tags, 1) { @@ -654,6 +677,7 @@ func TestEntRepository_CreateTransaction(t *testing.T) { t.Parallel() ctx := context.Background() + title := random.AlphaNumeric(t, 20) amount := random.Numeric(t, 100000) // Create user @@ -682,9 +706,10 @@ func TestEntRepository_CreateTransaction(t *testing.T) { nil, user.ID) require.NoError(t, err) - tx, err := repo.CreateTransaction(ctx, amount, target, nil, &group.ID, &request.ID) + tx, err := repo.CreateTransaction(ctx, title, amount, target, nil, &group.ID, &request.ID) assert.NoError(t, err) if assert.NotNil(t, tx) { + assert.Equal(t, title, tx.Title) assert.Equal(t, amount, tx.Amount) assert.Equal(t, target, tx.Target) assert.Len(t, tx.Tags, 0) @@ -701,6 +726,7 @@ func TestEntRepository_CreateTransaction(t *testing.T) { t.Parallel() ctx := context.Background() + title := random.AlphaNumeric(t, 20) amount := random.Numeric(t, 100000) // Create user @@ -727,10 +753,11 @@ func TestEntRepository_CreateTransaction(t *testing.T) { tx, err := repo.CreateTransaction( ctx, - amount, target, + title, amount, target, []*uuid.UUID{&tag.ID}, nil, &request.ID) assert.NoError(t, err) if assert.NotNil(t, tx) { + assert.Equal(t, title, tx.Title) assert.Equal(t, amount, tx.Amount) assert.Equal(t, target, tx.Target) if assert.Len(t, tx.Tags, 1) { @@ -746,12 +773,14 @@ func TestEntRepository_CreateTransaction(t *testing.T) { ctx := context.Background() // Create Transactions - target := random.AlphaNumeric(t, 20) + title := random.AlphaNumeric(t, 20) amount := random.Numeric(t, 100000) + target := random.AlphaNumeric(t, 20) - tx, err := repo.CreateTransaction(ctx, amount, target, nil, nil, nil) + tx, err := repo.CreateTransaction(ctx, title, amount, target, nil, nil, nil) assert.NoError(t, err) if assert.NotNil(t, tx) { + assert.Equal(t, title, tx.Title) assert.Equal(t, amount, tx.Amount) assert.Equal(t, target, tx.Target) assert.Len(t, tx.Tags, 0) @@ -764,12 +793,14 @@ func TestEntRepository_CreateTransaction(t *testing.T) { ctx := context.Background() // Create Transactions - target := random.AlphaNumeric(t, 20) + title := random.AlphaNumeric(t, 20) amount := -1 * random.Numeric(t, 100000) + target := random.AlphaNumeric(t, 20) - tx, err := repo.CreateTransaction(ctx, amount, target, nil, nil, nil) + tx, err := repo.CreateTransaction(ctx, title, amount, target, nil, nil, nil) assert.NoError(t, err) if assert.NotNil(t, tx) { + assert.Equal(t, title, tx.Title) assert.Equal(t, amount, tx.Amount) assert.Equal(t, target, tx.Target) assert.Len(t, tx.Tags, 0) @@ -788,6 +819,7 @@ func TestEntRepository_UpdateTransaction(t *testing.T) { t.Parallel() ctx := context.Background() + title := random.AlphaNumeric(t, 20) amount := random.Numeric(t, 100000) // Create user @@ -822,11 +854,12 @@ func TestEntRepository_UpdateTransaction(t *testing.T) { tx, err := repo.CreateTransaction( ctx, - amount, target, + title, amount, target, []*uuid.UUID{&tag.ID}, &group.ID, &request.ID) require.NoError(t, err) // Update Transactions + title = random.AlphaNumeric(t, 20) amount = random.Numeric(t, 100000) // Create tag @@ -853,10 +886,11 @@ func TestEntRepository_UpdateTransaction(t *testing.T) { tx, err = repo.UpdateTransaction( ctx, - tx.ID, amount, target, + tx.ID, title, amount, target, []*uuid.UUID{&tag.ID}, &group.ID, &request.ID) assert.NoError(t, err) if assert.NotNil(t, tx) { + assert.Equal(t, title, tx.Title) assert.Equal(t, amount, tx.Amount) assert.Equal(t, target, tx.Target) if assert.Len(t, tx.Tags, 1) { diff --git a/router/request.go b/router/request.go index 65fb980d..c9f3d79a 100644 --- a/router/request.go +++ b/router/request.go @@ -194,6 +194,15 @@ func (h Handlers) GetRequests(c echo.Context) error { g := c.QueryParam("group") group = &g } + var cratedBy *uuid.UUID + if c.QueryParam("created_by") != "" { + u, err := uuid.Parse(c.QueryParam("created_by")) + if err != nil { + h.Logger.Info("could not parse query parameter `created_by` as UUID", zap.Error(err)) + return echo.NewHTTPError(http.StatusBadRequest, err) + } + cratedBy = &u + } query := model.RequestQuery{ Sort: sort, Target: target, diff --git a/router/request_test.go b/router/request_test.go index 0d5c1ae4..03c7ddf7 100644 --- a/router/request_test.go +++ b/router/request_test.go @@ -391,6 +391,62 @@ func TestHandlers_GetRequests(t *testing.T) { } }) + t.Run("Success7", func(t *testing.T) { + t.Parallel() + ctrl := gomock.NewController(t) + + date := time.Now().Round(time.Second).UTC() + request := &model.RequestResponse{ + ID: uuid.New(), + Status: model.Submitted, + CreatedBy: uuid.New(), + Title: random.AlphaNumeric(t, 20), + Content: random.AlphaNumeric(t, 50), + CreatedAt: date, + UpdatedAt: date, + } + modelRequests := []*model.RequestResponse{request} + + e := echo.New() + req, err := http.NewRequest( + http.MethodGet, + fmt.Sprintf("/api/requests?created_by=%s", request.CreatedBy.String()), + nil) + require.NoError(t, err) + rec := httptest.NewRecorder() + c := e.NewContext(req, rec) + + h, err := NewTestHandlers(t, ctrl) + require.NoError(t, err) + h.Repository.MockRequestRepository. + EXPECT(). + GetRequests(c.Request().Context(), model.RequestQuery{CreatedBy: &request.CreatedBy}). + Return(modelRequests, nil) + err = h.Handlers.GetRequests(c) + if !assert.NoError(t, err) { + return + } + require.Equal(t, http.StatusOK, rec.Code) + var res []*RequestResponse + err = json.Unmarshal(rec.Body.Bytes(), &res) + require.NoError(t, err) + expectedBody := []*RequestResponse{ + { + ID: request.ID, + Status: request.Status, + CreatedAt: date, + UpdatedAt: date, + CreatedBy: request.CreatedBy, + Title: request.Title, + Content: request.Content, + Tags: []*TagOverview{}, + Targets: []*TargetOverview{}, + Comments: []*CommentDetail{}, + }, + } + require.Equal(t, expectedBody, res) + }) + t.Run("InvaildStatus", func(t *testing.T) { t.Parallel() ctrl := gomock.NewController(t) diff --git a/router/router.go b/router/router.go index 21984a4b..ca3a347f 100644 --- a/router/router.go +++ b/router/router.go @@ -49,19 +49,22 @@ func NewServer(h Handlers) *echo.Echo { apiRequests := api.Group("/requests", h.CheckLoginMiddleware) { apiRequests.GET("", h.GetRequests) - apiRequests.POST("", h.PostRequest, middleware.BodyDump(service.WebhookEventHandler)) + apiRequests.POST( + "", + h.PostRequest, + middleware.BodyDump(service.WebhookRequestsEventHandler)) apiRequestIDs := apiRequests.Group("/:requestID", retrieveRequestCreator) { apiRequestIDs.GET("", h.GetRequest) apiRequestIDs.PUT( "", h.PutRequest, - middleware.BodyDump(service.WebhookEventHandler), + middleware.BodyDump(service.WebhookRequestsEventHandler), h.CheckRequestCreatorMiddleware) apiRequestIDs.POST( "/comments", h.PostComment, - middleware.BodyDump(service.WebhookEventHandler)) + middleware.BodyDump(service.WebhookRequestsEventHandler)) apiRequestIDs.PUT("/status", h.PutStatus, h.CheckAdminOrRequestCreatorMiddleware) } } @@ -72,13 +75,13 @@ func NewServer(h Handlers) *echo.Echo { apiTransactions.POST( "", h.PostTransaction, - middleware.BodyDump(service.WebhookEventHandler), + middleware.BodyDump(service.WebhookTransactionsEventHandler), h.CheckAdminMiddleware) apiTransactions.GET("/:transactionID", h.GetTransaction) apiTransactions.PUT( "/:transactionID", h.PutTransaction, - middleware.BodyDump(service.WebhookEventHandler), + middleware.BodyDump(service.WebhookTransactionsEventHandler), h.CheckAdminMiddleware) } diff --git a/router/transaction.go b/router/transaction.go index 0028830c..9e1def8b 100644 --- a/router/transaction.go +++ b/router/transaction.go @@ -16,6 +16,7 @@ import ( type Transaction struct { ID uuid.UUID `json:"id"` + Title string `json:"title"` Amount int `json:"amount"` Target string `json:"target"` Request *uuid.UUID `json:"request"` @@ -26,6 +27,7 @@ type Transaction struct { } type TransactionOverview struct { + Title string `json:"title"` Amount int `json:"amount"` Targets []*string `json:"targets"` Tags []*uuid.UUID `json:"tags"` @@ -34,6 +36,7 @@ type TransactionOverview struct { } type TransactionOverviewWithOneTarget struct { + Title string `json:"title"` Amount int `json:"amount"` Target string `json:"target"` Tags []*uuid.UUID `json:"tags"` @@ -160,6 +163,7 @@ func (h Handlers) GetTransactions(c echo.Context) error { } return &Transaction{ ID: tx.ID, + Title: tx.Title, Amount: tx.Amount, Target: tx.Target, Request: tx.Request, @@ -175,6 +179,7 @@ func (h Handlers) GetTransactions(c echo.Context) error { func (h Handlers) PostTransaction(c echo.Context) error { var tx *TransactionOverview + // TODO: validate if err := c.Bind(&tx); err != nil { h.Logger.Info("could not get transaction overview from request", zap.Error(err)) return echo.NewHTTPError(http.StatusBadRequest, err) @@ -189,7 +194,7 @@ func (h Handlers) PostTransaction(c echo.Context) error { } created, err := h.Repository.CreateTransaction( ctx, - tx.Amount, *target, tx.Tags, tx.Group, tx.Request) + tx.Title, tx.Amount, *target, tx.Tags, tx.Group, tx.Request) if err != nil { h.Logger.Error("failed to create transaction in repository", zap.Error(err)) return echo.NewHTTPError(http.StatusInternalServerError, err) @@ -217,6 +222,7 @@ func (h Handlers) PostTransaction(c echo.Context) error { } res := Transaction{ ID: created.ID, + Title: created.Title, Amount: created.Amount, Target: created.Target, Request: created.Request, @@ -267,6 +273,7 @@ func (h Handlers) GetTransaction(c echo.Context) error { } res := Transaction{ ID: tx.ID, + Title: tx.Title, Amount: tx.Amount, Target: tx.Target, Request: tx.Request, @@ -287,6 +294,7 @@ func (h Handlers) PutTransaction(c echo.Context) error { } var tx *TransactionOverviewWithOneTarget + // TODO: validate if err := c.Bind(&tx); err != nil { h.Logger.Info( "could not get transaction overview with one target from request", @@ -297,7 +305,7 @@ func (h Handlers) PutTransaction(c echo.Context) error { ctx := c.Request().Context() updated, err := h.Repository.UpdateTransaction( ctx, - txID, tx.Amount, tx.Target, tx.Tags, tx.Group, tx.Request) + txID, tx.Title, tx.Amount, tx.Target, tx.Tags, tx.Group, tx.Request) if err != nil { h.Logger.Error("failed to update transaction in repository", zap.Error(err)) return echo.NewHTTPError(http.StatusInternalServerError, err) @@ -325,6 +333,7 @@ func (h Handlers) PutTransaction(c echo.Context) error { } res := Transaction{ ID: updated.ID, + Title: updated.Title, Amount: updated.Amount, Target: updated.Target, Request: updated.Request, diff --git a/router/transaction_test.go b/router/transaction_test.go index 5897ee09..b92775c0 100644 --- a/router/transaction_test.go +++ b/router/transaction_test.go @@ -39,6 +39,7 @@ func TestHandlers_GetTransactions(t *testing.T) { } tx1 := &model.TransactionResponse{ ID: uuid.New(), + Title: random.AlphaNumeric(t, 20), Amount: random.Numeric(t, 1000000), Target: random.AlphaNumeric(t, 20), Tags: []*model.Tag{ @@ -58,6 +59,7 @@ func TestHandlers_GetTransactions(t *testing.T) { tx2 := &model.TransactionResponse{ ID: uuid.New(), + Title: random.AlphaNumeric(t, 20), Amount: random.Numeric(t, 1000000), Target: random.AlphaNumeric(t, 20), Tags: []*model.Tag{ @@ -120,6 +122,7 @@ func TestHandlers_GetTransactions(t *testing.T) { } return &Transaction{ ID: tx.ID, + Title: tx.Title, Amount: tx.Amount, Target: tx.Target, Tags: tag, @@ -154,6 +157,7 @@ func TestHandlers_GetTransactions(t *testing.T) { } tx1 := &model.TransactionResponse{ ID: uuid.New(), + Title: random.AlphaNumeric(t, 20), Amount: random.Numeric(t, 1000000), Target: random.AlphaNumeric(t, 20), Tags: []*model.Tag{ @@ -173,6 +177,7 @@ func TestHandlers_GetTransactions(t *testing.T) { tx2 := &model.TransactionResponse{ ID: uuid.New(), + Title: random.AlphaNumeric(t, 20), Amount: random.Numeric(t, 1000000), Target: random.AlphaNumeric(t, 20), Tags: []*model.Tag{ @@ -233,6 +238,7 @@ func TestHandlers_GetTransactions(t *testing.T) { } return &Transaction{ ID: tx.ID, + Title: tx.Title, Amount: tx.Amount, Target: tx.Target, Tags: tag, @@ -267,6 +273,7 @@ func TestHandlers_GetTransactions(t *testing.T) { } tx1 := &model.TransactionResponse{ ID: uuid.New(), + Title: random.AlphaNumeric(t, 20), Amount: random.Numeric(t, 1000000), Target: random.AlphaNumeric(t, 20), Tags: []*model.Tag{ @@ -286,6 +293,7 @@ func TestHandlers_GetTransactions(t *testing.T) { tx2 := &model.TransactionResponse{ ID: uuid.New(), + Title: random.AlphaNumeric(t, 20), Amount: random.Numeric(t, 1000000), Target: random.AlphaNumeric(t, 20), Tags: []*model.Tag{ @@ -347,6 +355,7 @@ func TestHandlers_GetTransactions(t *testing.T) { } return &Transaction{ ID: tx.ID, + Title: tx.Title, Amount: tx.Amount, Target: tx.Target, Tags: tag, @@ -384,6 +393,7 @@ func TestHandlers_GetTransactions(t *testing.T) { tx1 := &model.TransactionResponse{ ID: uuid.New(), + Title: random.AlphaNumeric(t, 20), Amount: random.Numeric(t, 1000000), Target: target1, Tags: []*model.Tag{ @@ -403,6 +413,7 @@ func TestHandlers_GetTransactions(t *testing.T) { tx2 := &model.TransactionResponse{ ID: uuid.New(), + Title: random.AlphaNumeric(t, 20), Amount: random.Numeric(t, 1000000), Target: random.AlphaNumeric(t, 20), Tags: []*model.Tag{ @@ -466,6 +477,7 @@ func TestHandlers_GetTransactions(t *testing.T) { } return &Transaction{ ID: tx.ID, + Title: tx.Title, Amount: tx.Amount, Target: tx.Target, Tags: tag, @@ -503,6 +515,7 @@ func TestHandlers_GetTransactions(t *testing.T) { tx1 := &model.TransactionResponse{ ID: uuid.New(), + Title: random.AlphaNumeric(t, 20), Amount: random.Numeric(t, 1000000), Target: target1, Tags: []*model.Tag{ @@ -569,6 +582,7 @@ func TestHandlers_GetTransactions(t *testing.T) { } return &Transaction{ ID: tx.ID, + Title: tx.Title, Amount: tx.Amount, Target: tx.Target, Tags: tag, @@ -612,6 +626,7 @@ func TestHandlers_PostTransaction(t *testing.T) { tx1 := &model.TransactionResponse{ ID: uuid.New(), + Title: random.AlphaNumeric(t, 20), Amount: random.Numeric(t, 1000000), Target: target1, Tags: []*model.Tag{ @@ -635,9 +650,10 @@ func TestHandlers_PostTransaction(t *testing.T) { group := tx1.Group.ID e := echo.New() + // FIXME: json.Marshalを使う reqBody := fmt.Sprintf( - `{"amount": %d, "targets": ["%s"], "tags": ["%s"], "group": "%s"}`, - tx1.Amount, tx1.Target, tag.ID, group) + `{"title": "%s", "amount": %d, "targets": ["%s"], "tags": ["%s"], "group": "%s"}`, + tx1.Title, tx1.Amount, tx1.Target, tag.ID, group) req, err := http.NewRequest( http.MethodPost, "/api/transactions", @@ -652,7 +668,9 @@ func TestHandlers_PostTransaction(t *testing.T) { h.Repository.MockTransactionRepository. EXPECT(). - CreateTransaction(c.Request().Context(), tx1.Amount, tx1.Target, tags, &group, nil). + CreateTransaction( + c.Request().Context(), + tx1.Title, tx1.Amount, tx1.Target, tags, &group, nil). Return(tx1, nil) res := lo.Map(txs, func(tx *model.TransactionResponse, _ int) *Transaction { @@ -675,6 +693,7 @@ func TestHandlers_PostTransaction(t *testing.T) { } return &Transaction{ ID: tx.ID, + Title: tx.Title, Amount: tx.Amount, Target: tx.Target, Tags: tag, @@ -712,6 +731,7 @@ func TestHandlers_PostTransaction(t *testing.T) { tx := &model.TransactionResponse{ ID: uuid.New(), + Title: random.AlphaNumeric(t, 20), Amount: random.Numeric(t, 1000000), Target: target1, Tags: []*model.Tag{ @@ -748,9 +768,11 @@ func TestHandlers_PostTransaction(t *testing.T) { } e := echo.New() + // FIXME: json.Marshalを使う + // nolint:lll reqBody := fmt.Sprintf( - `{"amount": %d, "targets": ["%s"], "tags": ["%s"], "group": "%s", "request": "%s"}`, - tx.Amount, tx.Target, tag.ID, group, request.ID) + `{"title": "%s", "amount": %d, "targets": ["%s"], "tags": ["%s"], "group": "%s", "request": "%s"}`, + tx.Title, tx.Amount, tx.Target, tag.ID, group, request.ID) req, err := http.NewRequest( http.MethodPost, "/api/transactions", @@ -767,7 +789,7 @@ func TestHandlers_PostTransaction(t *testing.T) { EXPECT(). CreateTransaction( c.Request().Context(), - tx.Amount, tx.Target, + tx.Title, tx.Amount, tx.Target, tags, &group, &request.ID). Return(tx, nil) @@ -791,6 +813,7 @@ func TestHandlers_PostTransaction(t *testing.T) { res := []*Transaction{ { ID: tx.ID, + Title: tx.Title, Amount: tx.Amount, Target: tx.Target, Tags: to, @@ -807,6 +830,9 @@ func TestHandlers_PostTransaction(t *testing.T) { assert.Equal(t, string(resBody), strings.TrimRight(rec.Body.String(), "\n")) } }) + + // TODO: FailWithoutTitle + // PostTransactionにvalidationが入ってから } func TestHandlers_GetTransaction(t *testing.T) { @@ -827,6 +853,7 @@ func TestHandlers_GetTransaction(t *testing.T) { tx := &model.TransactionResponse{ ID: uuid.New(), + Title: random.AlphaNumeric(t, 20), Amount: random.Numeric(t, 1000000), Target: random.AlphaNumeric(t, 20), Tags: []*model.Tag{ @@ -861,7 +888,6 @@ func TestHandlers_GetTransaction(t *testing.T) { GetTransaction(c.Request().Context(), tx.ID). Return(tx, nil) - var resOverview Transaction to := lo.Map(tx.Tags, func(modelTag *model.Tag, _ int) *TagOverview { return &TagOverview{ ID: modelTag.ID, @@ -879,8 +905,9 @@ func TestHandlers_GetTransaction(t *testing.T) { CreatedAt: tx.Group.CreatedAt, UpdatedAt: tx.Group.UpdatedAt, } - resOverview = Transaction{ + resOverview := Transaction{ ID: tx.ID, + Title: tx.Title, Amount: tx.Amount, Target: tx.Target, Tags: to, @@ -924,6 +951,7 @@ func TestHandlers_PutTransaction(t *testing.T) { tx := &model.TransactionResponse{ ID: uuid.New(), + Title: random.AlphaNumeric(t, 20), Amount: random.Numeric(t, 1000000), Target: random.AlphaNumeric(t, 20), Tags: []*model.Tag{ @@ -986,11 +1014,10 @@ func TestHandlers_PutTransaction(t *testing.T) { EXPECT(). UpdateTransaction( c.Request().Context(), - tx.ID, updated.Amount, updated.Target, + tx.ID, updated.Title, updated.Amount, updated.Target, updatedTags, nil, nil). Return(updated, nil) - var resOverview Transaction to := lo.Map(updated.Tags, func(modelTag *model.Tag, _ int) *TagOverview { return &TagOverview{ ID: modelTag.ID, @@ -1007,8 +1034,9 @@ func TestHandlers_PutTransaction(t *testing.T) { CreatedAt: updated.Group.CreatedAt, UpdatedAt: updated.Group.UpdatedAt, } - resOverview = Transaction{ + resOverview := Transaction{ ID: tx.ID, + Title: updated.Title, Amount: updated.Amount, Target: updated.Target, Tags: to, diff --git a/router/user.go b/router/user.go index a14e59d4..f41965fd 100644 --- a/router/user.go +++ b/router/user.go @@ -8,6 +8,7 @@ import ( "github.com/labstack/echo-contrib/session" "github.com/labstack/echo/v4" "github.com/samber/lo" + "github.com/traPtitech/Jomon/ent" "github.com/traPtitech/Jomon/model" "go.uber.org/zap" ) @@ -79,17 +80,39 @@ func (h Handlers) UpdateUserInfo(c echo.Context) error { }) } +func userFromModelUser(u model.User) User { + return User{ + ID: u.ID, + Name: u.Name, + DisplayName: u.DisplayName, + Admin: u.Admin, + CreatedAt: u.CreatedAt, + UpdatedAt: u.UpdatedAt, + DeletedAt: u.DeletedAt, + } +} + func (h Handlers) GetMe(c echo.Context) error { sess, err := session.Get(h.SessionName, c) if err != nil { h.Logger.Error("failed to get session", zap.Error(err)) return echo.NewHTTPError(http.StatusInternalServerError, err) } - user, ok := sess.Values[sessionUserKey].(User) + userInSession, ok := sess.Values[sessionUserKey].(User) if !ok { h.Logger.Error("failed to parse stored session as user info") return echo.NewHTTPError(http.StatusInternalServerError, "failed to get user info") } + modelUser, err := h.Repository.GetUserByID(c.Request().Context(), userInSession.ID) + if err != nil { + if ent.IsNotFound(err) { + h.Logger.Error("failed to find user from DB by ID") + return c.JSON(http.StatusNotFound, err) + } + h.Logger.Error("failed to get user by ID") + return c.JSON(http.StatusInternalServerError, err) + } + user := userFromModelUser(*modelUser) return c.JSON(http.StatusOK, user) } diff --git a/router/user_test.go b/router/user_test.go index b5f28adb..b08047ac 100644 --- a/router/user_test.go +++ b/router/user_test.go @@ -289,7 +289,7 @@ func TestHandlers_GetMe(t *testing.T) { t.Run("Success", func(t *testing.T) { t.Parallel() ctrl := gomock.NewController(t) - accessUser := makeUser(t, false) + accessUser := makeUser(t, random.Numeric(t, 2) == 1) user := User{ ID: accessUser.ID, Name: accessUser.Name, @@ -321,6 +321,11 @@ func TestHandlers_GetMe(t *testing.T) { sess.Values[sessionUserKey] = user require.NoError(t, sess.Save(c.Request(), c.Response())) + h.Repository.MockUserRepository. + EXPECT(). + GetUserByID(c.Request().Context(), user.ID). + Return(accessUser, nil) + err = h.Handlers.GetMe(c) if assert.NoError(t, err) { assert.Equal(t, http.StatusOK, rec.Code) diff --git a/service/webhook.go b/service/webhook.go index c2059158..1f1a3cdd 100644 --- a/service/webhook.go +++ b/service/webhook.go @@ -36,7 +36,15 @@ type CommentApplication struct { Comment string `json:"comment"` } -type TransactionRequestApplication struct { +type TransactionPostRequestApplication struct { + ID uuid.UUID `json:"id"` + Amount int `json:"amount"` + Target string `json:"target"` + Tags []*Tag `json:"tags"` + Group *Group `json:"group"` +} + +type TransactionPutRequestApplication struct { ID uuid.UUID `json:"id"` Amount int `json:"amount"` Target string `json:"target"` @@ -72,117 +80,133 @@ type Webhook struct { ID string } -func WebhookEventHandler(c echo.Context, reqBody, resBody []byte) { +func WebhookRequestsEventHandler(c echo.Context, reqBody, resBody []byte) { webhookSecret := os.Getenv("WEBHOOK_SECRET") webhookChannelId := os.Getenv("WEBHOOK_CHANNEL_ID") webhookId := os.Getenv("WEBHOOK_ID") var message string - if strings.Contains(c.Request().URL.Path, "/api/requests") { - if strings.Contains(c.Request().URL.Path, "/comments") { - resApp := new(CommentApplication) - err := json.Unmarshal(resBody, resApp) - if err != nil { - return - } - splitedPath := strings.Split(c.Request().URL.Path, "/") + if strings.Contains(c.Request().URL.Path, "/comments") { + resApp := new(CommentApplication) + err := json.Unmarshal(resBody, resApp) + if err != nil { + return + } + splitedPath := strings.Split(c.Request().URL.Path, "/") - message += fmt.Sprintf( - "## :comment:[申請](%s/requests/%s)", - "https://jomon.trap.jp", - splitedPath[3]) - message += "に対する" - message += fmt.Sprintf( - "[コメント](%s/requests/%s/comments/%s)", - "https://jomon.trap.jp", - splitedPath[3], - resApp.ID) - message += "が作成されました\n\n" - message += resApp.Comment + "\n" - } else { - resApp := new(RequestApplication) - err := json.Unmarshal(resBody, resApp) - if err != nil { - return - } - if c.Request().Method == http.MethodPost { - message += "## :receipt:申請が作成されました\n" - } else if c.Request().Method == http.MethodPut { - message += "## :receipt:申請が更新されました\n" - } + message += fmt.Sprintf( + "## :comment:[申請](%s/requests/%s)", + "https://jomon.trap.jp", + splitedPath[3]) + message += "に対する" + message += fmt.Sprintf( + "[コメント](%s/requests/%s/comments/%s)", + "https://jomon.trap.jp", + splitedPath[3], + resApp.ID) + message += "が作成されました\n\n" + message += resApp.Comment + "\n" + } else { + resApp := new(RequestApplication) + err := json.Unmarshal(resBody, resApp) + if err != nil { + return + } + if c.Request().Method == http.MethodPost { + message += "## :receipt:申請が作成されました\n" + } else if c.Request().Method == http.MethodPut { + message += "## :receipt:申請が更新されました\n" + } - message += fmt.Sprintf( - "### [%s](%s/applications/%s)\n", - resApp.Title, - "https://jomon.trap.jp", - resApp.ID) - - amount := lo.Reduce(resApp.Targets, func(amo int, target *Target, _ int) int { - return amo + target.Amount - }, 0) - message += fmt.Sprintf("- 支払金額: %d円\n", amount) - - if resApp.Group != nil { - message += fmt.Sprintf("- 請求先グループ: %s\n", resApp.Group.Name) - } - - if len(resApp.Tags) != 0 { - tags := lo.Map(resApp.Tags, func(tag *Tag, _ int) string { - return tag.Name - }) - message += fmt.Sprintf("- タグ: %s", strings.Join(tags, ", ")) - } - message += "\n\n" - message += resApp.Content + "\n" + message += fmt.Sprintf( + "### [%s](%s/applications/%s)\n", + resApp.Title, + "https://jomon.trap.jp", + resApp.ID) + + amount := lo.Reduce(resApp.Targets, func(amo int, target *Target, _ int) int { + return amo + target.Amount + }, 0) + message += fmt.Sprintf("- 支払金額: %d円\n", amount) + + if resApp.Group != nil { + message += fmt.Sprintf("- 請求先グループ: %s\n", resApp.Group.Name) } - } else if strings.Contains(c.Request().URL.Path, "/api/transactions") { - var resApps []TransactionRequestApplication + + if len(resApp.Tags) != 0 { + tags := lo.Map(resApp.Tags, func(tag *Tag, _ int) string { + return tag.Name + }) + message += fmt.Sprintf("- タグ: %s", strings.Join(tags, ", ")) + } + message += "\n\n" + message += resApp.Content + "\n" + } + _ = RequestWebhook(message, webhookSecret, webhookChannelId, webhookId, 1) +} + +func WebhookTransactionsEventHandler(c echo.Context, reqBody, resBody []byte) { + webhookSecret := os.Getenv("WEBHOOK_SECRET") + webhookChannelId := os.Getenv("WEBHOOK_CHANNEL_ID") + webhookId := os.Getenv("WEBHOOK_ID") + var message string + + if c.Request().Method == http.MethodPost { + var resApps []TransactionPostRequestApplication err := json.Unmarshal(resBody, &resApps) - resApp := resApps[0] - if err != nil { + if err != nil || len(resApps) < 1 { return } - if c.Request().Method == http.MethodPost { + message += fmt.Sprintf( + "## :scroll:[入出金記録](%s/transactions/%s)が新規作成されました\n", + "https://jomon.trap.jp", + resApps[0].ID) + targets := lo.Map( + resApps, func(resApp TransactionPostRequestApplication, _ int) string { + return resApp.Target + }) + if resApps[0].Amount < 0 { message += fmt.Sprintf( - "## :scroll:[入出金記録](%s/transactions/%s)が新規作成されました\n", - "https://jomon.trap.jp", - resApp.ID) - } else if c.Request().Method == http.MethodPut { + "- %sへの支払い\n - 支払い金額: 計%d円(一人当たりへの支払い金額: %d円)\n", + strings.Join(targets, " "), + -len(resApps)*resApps[0].Amount, + -resApps[0].Amount) + } else { message += fmt.Sprintf( - "## :scroll:[入出金記録](%s/transactions/%s)が修正されました\n", - "https://jomon.trap.jp", - resApp.ID) + "- %sからの振込\n - 受け取り金額: 計%d円(一人当たりからの受け取り金額: %d円)\n", + strings.Join(targets, " "), + len(resApps)*resApps[0].Amount, + resApps[0].Amount) + } + if resApps[0].Group != nil { + message += fmt.Sprintf("- 関連するグループ: %s\n", resApps[0].Group.Name) + } + if len(resApps[0].Tags) != 0 { + tags := lo.Map(resApps[0].Tags, func(tag *Tag, _ int) string { + return tag.Name + }) + message += fmt.Sprintf("- タグ: %s", strings.Join(tags, ", ")) } - if len(resApps) == 1 { - if resApp.Amount < 0 { - message += fmt.Sprintf( - "- `%s`への支払い\n - 支払い金額: %d円\n", - resApp.Target, - -resApp.Amount) - } else { - message += fmt.Sprintf( - "- `%s`からの振込\n - 受け取り金額: %d円\n", - resApp.Target, - resApp.Amount) - } + } else if c.Request().Method == http.MethodPut { + var resApp TransactionPutRequestApplication + err := json.Unmarshal(resBody, &resApp) + if err != nil { + return + } + message += fmt.Sprintf( + "## :scroll:[入出金記録](%s/transactions/%s)が修正されました\n", + "https://jomon.trap.jp", + resApp.ID) + if resApp.Amount < 0 { + message += fmt.Sprintf( + "- `%s`への支払い\n - 支払い金額: %d円\n", + resApp.Target, + -resApp.Amount) } else { - targets := lo.Map( - resApps, func(resApp TransactionRequestApplication, _ int) string { - return resApp.Target - }) - if resApp.Amount < 0 { - message += fmt.Sprintf( - "- %sへの支払い\n - 支払い金額: 計%d円(一人当たりへの支払い金額: %d円)\n", - strings.Join(targets, " "), - -len(resApps)*resApp.Amount, - -resApp.Amount) - } else { - message += fmt.Sprintf( - "- %sからの振込\n - 受け取り金額: 計%d円(一人当たりからの受け取り金額: %d円)\n", - strings.Join(targets, " "), - len(resApps)*resApp.Amount, - resApp.Amount) - } + message += fmt.Sprintf( + "- `%s`からの振込\n - 受け取り金額: %d円\n", + resApp.Target, + resApp.Amount) } if resApp.Group != nil { message += fmt.Sprintf("- 関連するグループ: %s\n", resApp.Group.Name) @@ -194,7 +218,6 @@ func WebhookEventHandler(c echo.Context, reqBody, resBody []byte) { message += fmt.Sprintf("- タグ: %s", strings.Join(tags, ", ")) } } - _ = RequestWebhook(message, webhookSecret, webhookChannelId, webhookId, 1) }