Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PART-1] Add transaction tax report #380

Merged
5 changes: 5 additions & 0 deletions workers/loc.api/di/app.deps.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ const {
fullTaxReportCsvWriter
} = require('../generate-report-file/csv-writer')
const FullTaxReport = require('../sync/full.tax.report')
const TransactionTaxReport = require('../sync/transaction.tax.report')
const WeightedAveragesReport = require('../sync/weighted.averages.report')
const SqliteDbMigrator = require(
'../sync/dao/db-migrations/sqlite.db.migrator'
Expand Down Expand Up @@ -151,6 +152,7 @@ module.exports = ({
['_positionsSnapshot', TYPES.PositionsSnapshot],
['_fullSnapshotReport', TYPES.FullSnapshotReport],
['_fullTaxReport', TYPES.FullTaxReport],
['_transactionTaxReport', TYPES.TransactionTaxReport],
['_tradedVolume', TYPES.TradedVolume],
['_totalFeesReport', TYPES.TotalFeesReport],
['_performingLoan', TYPES.PerformingLoan],
Expand Down Expand Up @@ -393,6 +395,9 @@ module.exports = ({
)
bind(TYPES.FullTaxReport)
.to(FullTaxReport)
bind(TYPES.TransactionTaxReport)
.to(TransactionTaxReport)
.inSingletonScope()
rebind(TYPES.WeightedAveragesReport)
.to(WeightedAveragesReport)
rebind(TYPES.ReportFileJobData)
Expand Down
3 changes: 2 additions & 1 deletion workers/loc.api/di/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,6 @@ module.exports = {
SyncUserStepData: Symbol.for('SyncUserStepData'),
SyncUserStepDataFactory: Symbol.for('SyncUserStepDataFactory'),
HTTPRequest: Symbol.for('HTTPRequest'),
SummaryByAsset: Symbol.for('SummaryByAsset')
SummaryByAsset: Symbol.for('SummaryByAsset'),
TransactionTaxReport: Symbol.for('TransactionTaxReport')
}
44 changes: 44 additions & 0 deletions workers/loc.api/generate-report-file/report.file.job.data.js
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,50 @@ class ReportFileJobData extends BaseReportFileJobData {
return jobData
}

async getTransactionTaxReportFileJobData (
args,
uId,
uInfo
) {
checkParams(args, 'paramsSchemaForTransactionTaxReportFile')

const {
userId,
userInfo
} = await checkJobAndGetUserData(
this.rService,
uId,
uInfo
)

const reportFileArgs = getReportFileArgs(args)

const jobData = {
userInfo,
userId,
name: 'getTransactionTaxReport',
fileNamesMap: [['getTransactionTaxReport', 'transaction-tax-report']],
args: reportFileArgs,
propNameForPagination: null,
columnsCsv: {
asset: 'DESCRIPTION OF PROPERTY',
amount: 'AMOUNT',
mtsAcquired: 'DATE ACQUIRED',
mtsSold: 'DATE SOLD',
proceeds: 'PROCEEDS',
cost: 'COST',
gainOrLoss: 'GAIN OR LOSS'
},
formatSettings: {
asset: 'symbol',
mtsAcquired: 'date',
mtsSold: 'date'
}
}

return jobData
}

async getTradedVolumeFileJobData (
args,
uId,
Expand Down
30 changes: 30 additions & 0 deletions workers/loc.api/helpers/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,25 @@ const paramsSchemaForFullTaxReportApi = {
}
}

const paramsSchemaForTransactionTaxReportApi = {
type: 'object',
properties: {
end: {
type: 'integer'
},
start: {
type: 'integer'
},
strategy: {
type: 'string',
enum: [
'FIFO',
'LIFO'
]
}
}
}

const paramsSchemaForWinLossApi = {
type: 'object',
properties: {
Expand Down Expand Up @@ -412,6 +431,15 @@ const paramsSchemaForFullTaxReportFile = {
}
}

const paramsSchemaForTransactionTaxReportFile = {
type: 'object',
properties: {
...cloneDeep(paramsSchemaForTransactionTaxReportApi.properties),
timezone,
dateFormat
}
}

const paramsSchemaForTradedVolumeFile = {
type: 'object',
properties: {
Expand Down Expand Up @@ -460,6 +488,7 @@ module.exports = {
paramsSchemaForPositionsSnapshotApi,
paramsSchemaForFullSnapshotReportApi,
paramsSchemaForFullTaxReportApi,
paramsSchemaForTransactionTaxReportApi,
paramsSchemaForTradedVolumeApi,
paramsSchemaForTotalFeesReportApi,
paramsSchemaForPerformingLoanApi,
Expand All @@ -471,6 +500,7 @@ module.exports = {
paramsSchemaForPositionsSnapshotFile,
paramsSchemaForFullSnapshotReportFile,
paramsSchemaForFullTaxReportFile,
paramsSchemaForTransactionTaxReportFile,
paramsSchemaForTradedVolumeFile,
paramsSchemaForTotalFeesReportFile,
paramsSchemaForPerformingLoanFile,
Expand Down
36 changes: 36 additions & 0 deletions workers/loc.api/service.report.framework.js
Original file line number Diff line number Diff line change
Expand Up @@ -1409,6 +1409,28 @@ class FrameworkReportService extends ReportService {
}, 'getFullTaxReport', args, cb)
}

getTransactionTaxReport (space, args, cb) {
return this._privResponder(async () => {
await this._dataConsistencyChecker
.check(this._CHECKER_NAMES.TRANSACTION_TAX_REPORT, args)

checkParams(args, 'paramsSchemaForTransactionTaxReportApi')

return this._transactionTaxReport.getTransactionTaxReport(args)
}, 'getTransactionTaxReport', args, cb)
}

makeTrxTaxReportInBackground (space, args, cb) {
return this._privResponder(async () => {
await this._dataConsistencyChecker
.check(this._CHECKER_NAMES.TRANSACTION_TAX_REPORT, args)

checkParams(args, 'paramsSchemaForTransactionTaxReportApi')

return this._transactionTaxReport.makeTrxTaxReportInBackground(args)
}, 'makeTrxTaxReportInBackground', args, cb)
}

getTradedVolume (space, args, cb) {
return this._privResponder(async () => {
await this._dataConsistencyChecker
Expand Down Expand Up @@ -1553,6 +1575,20 @@ class FrameworkReportService extends ReportService {
}, 'getFullTaxReportFile', args, cb)
}

/**
* @deprecated
*/
getTransactionTaxReportCsv (...args) { return this.getTransactionTaxReportFile(...args) }

getTransactionTaxReportFile (space, args, cb) {
return this._responder(() => {
return this._generateReportFile(
'getTransactionTaxReportFileJobData',
args
)
}, 'getTransactionTaxReportFile', args, cb)
}

/**
* @deprecated
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module.exports = {
POSITIONS_SNAPSHOT: 'getPositionsSnapshot',
FULL_SNAPSHOT_REPORT: 'getFullSnapshotReport',
FULL_TAX_REPORT: 'getFullTaxReport',
TRANSACTION_TAX_REPORT: 'getTransactionTaxReport',
TRADED_VOLUME: 'getTradedVolume',
TOTAL_FEES_REPORT: 'getTotalFeesReport',
PERFORMING_LOAN: 'getPerformingLoan',
Expand Down
14 changes: 14 additions & 0 deletions workers/loc.api/sync/data.consistency.checker/checkers.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,20 @@ class Checkers {
})
}

[CHECKER_NAMES.TRANSACTION_TAX_REPORT] (auth) {
return this.syncCollsManager
.haveCollsBeenSyncedUpToDate({
auth,
params: {
schema: [
this.SYNC_API_METHODS.TRADES,
this.SYNC_API_METHODS.LEDGERS,
this.SYNC_API_METHODS.MOVEMENTS
]
}
})
}

[CHECKER_NAMES.TRADED_VOLUME] (auth) {
return this.syncCollsManager
.haveCollsBeenSyncedUpToDate({
Expand Down
7 changes: 7 additions & 0 deletions workers/loc.api/sync/transaction.tax.report/helpers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict'

const TRX_TAX_STRATEGIES = require('./trx.tax.strategies')

module.exports = {
TRX_TAX_STRATEGIES
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use strict'

const TRX_TAX_STRATEGIES = {
FIFO: 'FIFO',
LIFO: 'LIFO'
}

module.exports = TRX_TAX_STRATEGIES
84 changes: 84 additions & 0 deletions workers/loc.api/sync/transaction.tax.report/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
'use strict'

const {
TRX_TAX_STRATEGIES
} = require('./helpers')

const { decorateInjectable } = require('../../di/utils')

const depsTypes = (TYPES) => [
TYPES.DAO,
TYPES.Authenticator,
TYPES.SyncSchema,
TYPES.ALLOWED_COLLS,
TYPES.SYNC_API_METHODS,
TYPES.Movements,
TYPES.RService,
TYPES.GetDataFromApi,
TYPES.WSEventEmitterFactory,
TYPES.Logger
]
class TransactionTaxReport {
constructor (
dao,
authenticator,
syncSchema,
ALLOWED_COLLS,
SYNC_API_METHODS,
movements,
rService,
getDataFromApi,
wsEventEmitterFactory,
logger
) {
this.dao = dao
this.authenticator = authenticator
this.syncSchema = syncSchema
this.ALLOWED_COLLS = ALLOWED_COLLS
this.SYNC_API_METHODS = SYNC_API_METHODS
this.movements = movements
this.rService = rService
this.getDataFromApi = getDataFromApi
this.wsEventEmitterFactory = wsEventEmitterFactory
this.logger = logger

this.tradesModel = this.syncSchema.getModelsMap()
.get(this.ALLOWED_COLLS.TRADES)
}

async makeTrxTaxReportInBackground (args = {}) {
const { auth, params } = args ?? {}
const user = await this.authenticator
.verifyRequestUser({ auth })
const _args = { auth: user, params }

this.wsEventEmitterFactory()
.emitTrxTaxReportGenerationInBackgroundToOne(() => {
return this.getTransactionTaxReport(_args)
}, user)
.then(() => {}, (err) => {
this.logger.error(`TRX_TAX_REPORT_GEN_FAILED: ${err.stack || err}`)
})

return true
}

async getTransactionTaxReport (args = {}) {
const { auth, params } = args ?? {}
const start = params.start ?? 0
const end = params.end ?? Date.now()
const strategy = params.strategy ?? TRX_TAX_STRATEGIES.LIFO
const user = await this.authenticator
.verifyRequestUser({ auth })

const isFIFO = strategy === TRX_TAX_STRATEGIES.FIFO
const isLIFO = strategy === TRX_TAX_STRATEGIES.LIFO

// TODO:
return []
}
}

decorateInjectable(TransactionTaxReport, depsTypes)

module.exports = TransactionTaxReport
15 changes: 15 additions & 0 deletions workers/loc.api/ws-transport/ws.event.emitter.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,21 @@ class WSEventEmitter extends AbstractWSEventEmitter {
}, 'emitBfxUnamePwdAuthRequired')
}

emitTrxTaxReportGenerationInBackgroundToOne (
handler = () => {},
auth = {}
) {
return this.emit(async (user, ...args) => {
if (this.isNotTargetUser(auth, user)) {
return { isNotEmitted: true }
}

return typeof handler === 'function'
? await handler(user, ...args)
: handler
}, 'emitTrxTaxReportGenerationInBackgroundToOne')
}

async emitRedirectingRequestsStatusToApi (
handler = () => {}
) {
Expand Down