diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index f31dfc93d..9ebfa7dd8 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -10,7 +10,7 @@ Decimal.set({ }) const constants = { - DB_VERSION: '0051-add_delete_by_to_contributions', + DB_VERSION: '0052-add_updated_at_to_contributions', DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0 LOG4JS_CONFIG: 'log4js-config.json', // default log level on production should be info diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index aec7bc44d..ede61b413 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -13,6 +13,8 @@ import { Contribution, ContributionListResult } from '@model/Contribution' import { UnconfirmedContribution } from '@model/UnconfirmedContribution' import { validateContribution, getUserCreation, updateCreations } from './util/creations' import { MEMO_MAX_CHARS, MEMO_MIN_CHARS } from './const/const' +import { ContributionMessage } from '@entity/ContributionMessage' +import { ContributionMessageType } from '@enum/MessageType' import { Event, EventContributionCreate, @@ -192,7 +194,17 @@ export class ContributionResolver { logger.error('user of the pending contribution and send user does not correspond') throw new Error('user of the pending contribution and send user does not correspond') } - + if ( + contributionToUpdate.contributionStatus !== ContributionStatus.IN_PROGRESS && + contributionToUpdate.contributionStatus !== ContributionStatus.PENDING + ) { + logger.error( + `Contribution can not be updated since the state is ${contributionToUpdate.contributionStatus}`, + ) + throw new Error( + `Contribution can not be updated since the state is ${contributionToUpdate.contributionStatus}`, + ) + } const creationDateObj = new Date(creationDate) let creations = await getUserCreation(user.id) if (contributionToUpdate.contributionDate.getMonth() === creationDateObj.getMonth()) { @@ -204,10 +216,28 @@ export class ContributionResolver { // all possible cases not to be true are thrown in this function validateContribution(creations, amount, creationDateObj) + + const contributionMessage = ContributionMessage.create() + contributionMessage.contributionId = contributionId + contributionMessage.createdAt = contributionToUpdate.updatedAt + ? contributionToUpdate.updatedAt + : contributionToUpdate.createdAt + const changeMessage = `${contributionToUpdate.contributionDate} + --- + ${contributionToUpdate.memo} + --- + ${contributionToUpdate.amount}` + contributionMessage.message = changeMessage + contributionMessage.isModerator = false + contributionMessage.userId = user.id + contributionMessage.type = ContributionMessageType.HISTORY + ContributionMessage.save(contributionMessage) + contributionToUpdate.amount = amount contributionToUpdate.memo = memo contributionToUpdate.contributionDate = new Date(creationDate) contributionToUpdate.contributionStatus = ContributionStatus.PENDING + contributionToUpdate.updatedAt = new Date() dbContribution.save(contributionToUpdate) const event = new Event() diff --git a/database/entity/0052-add_updated_at_to_contributions/Contribution.ts b/database/entity/0052-add_updated_at_to_contributions/Contribution.ts new file mode 100644 index 000000000..2242a753f --- /dev/null +++ b/database/entity/0052-add_updated_at_to_contributions/Contribution.ts @@ -0,0 +1,95 @@ +import Decimal from 'decimal.js-light' +import { + BaseEntity, + Column, + Entity, + PrimaryGeneratedColumn, + DeleteDateColumn, + JoinColumn, + ManyToOne, + OneToMany, +} from 'typeorm' +import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' +import { User } from '../User' +import { ContributionMessage } from '../ContributionMessage' + +@Entity('contributions') +export class Contribution extends BaseEntity { + @PrimaryGeneratedColumn('increment', { unsigned: true }) + id: number + + @Column({ unsigned: true, nullable: false, name: 'user_id' }) + userId: number + + @ManyToOne(() => User, (user) => user.contributions) + @JoinColumn({ name: 'user_id' }) + user: User + + @Column({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP', name: 'created_at' }) + createdAt: Date + + @Column({ type: 'datetime', nullable: false, name: 'contribution_date' }) + contributionDate: Date + + @Column({ length: 255, nullable: false, collation: 'utf8mb4_unicode_ci' }) + memo: string + + @Column({ + type: 'decimal', + precision: 40, + scale: 20, + nullable: false, + transformer: DecimalTransformer, + }) + amount: Decimal + + @Column({ unsigned: true, nullable: true, name: 'moderator_id' }) + moderatorId: number + + @Column({ unsigned: true, nullable: true, name: 'contribution_link_id' }) + contributionLinkId: number + + @Column({ unsigned: true, nullable: true, name: 'confirmed_by' }) + confirmedBy: number + + @Column({ nullable: true, name: 'confirmed_at' }) + confirmedAt: Date + + @Column({ unsigned: true, nullable: true, name: 'denied_by' }) + deniedBy: number + + @Column({ nullable: true, name: 'denied_at' }) + deniedAt: Date + + @Column({ + name: 'contribution_type', + length: 12, + nullable: false, + collation: 'utf8mb4_unicode_ci', + }) + contributionType: string + + @Column({ + name: 'contribution_status', + length: 12, + nullable: false, + collation: 'utf8mb4_unicode_ci', + }) + contributionStatus: string + + @Column({ unsigned: true, nullable: true, name: 'transaction_id' }) + transactionId: number + + @Column({ nullable: true, name: 'updated_at' }) + updatedAt: Date + + @DeleteDateColumn({ name: 'deleted_at' }) + deletedAt: Date | null + + @DeleteDateColumn({ unsigned: true, nullable: true, name: 'deleted_by' }) + deletedBy: number + + @OneToMany(() => ContributionMessage, (message) => message.contribution) + @JoinColumn({ name: 'contribution_id' }) + messages?: ContributionMessage[] +} diff --git a/database/entity/Contribution.ts b/database/entity/Contribution.ts index 4b1dfc9c8..0441e7a1f 100644 --- a/database/entity/Contribution.ts +++ b/database/entity/Contribution.ts @@ -1 +1 @@ -export { Contribution } from './0051-add_delete_by_to_contributions/Contribution' +export { Contribution } from './0052-add_updated_at_to_contributions/Contribution' diff --git a/database/migrations/0052-add_updated_at_to_contributions.ts b/database/migrations/0052-add_updated_at_to_contributions.ts new file mode 100644 index 000000000..e7cc5b7b4 --- /dev/null +++ b/database/migrations/0052-add_updated_at_to_contributions.ts @@ -0,0 +1,12 @@ +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn( + `ALTER TABLE \`contributions\` ADD COLUMN \`updated_at\` datetime DEFAULT NULL AFTER \`transaction_id\`;`, + ) +} + +export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn(`ALTER TABLE \`contributions\` DROP COLUMN \`updated_at\`;`) +}