-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
21 changed files
with
424 additions
and
112 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
export class BqTransacao { | ||
id: number; | ||
data: Date; | ||
hora: number; | ||
datetime_transacao: Date; | ||
datetime_processamento: Date; | ||
datetime_captura: Date; | ||
modo: string; | ||
id_consorcio: string; | ||
consorcio: string; | ||
id_operadora: string; | ||
operadora: string; | ||
servico: string; | ||
sentido: string; | ||
id_veiculo: number; | ||
id_cliente: string; | ||
id_transacao: string; | ||
tipo_pagamento: string; | ||
tipo_transacao: string; | ||
tipo_gratuidade: string; | ||
tipo_integracao: string; | ||
id_integracao: number; | ||
latitude: number; | ||
longitude: number; | ||
stop_id: number; | ||
stop_lat: number; | ||
stop_lon: number; | ||
valor_transacao: number; | ||
versao: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
export interface IBqFetchTransacao { | ||
cpfCnpj?: string; | ||
startDate?: Date; | ||
endDate?: Date; | ||
limit?: number; | ||
offset?: number; | ||
getToday?: boolean; | ||
previousDays?: boolean; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/** | ||
* Ticket revenues integration type map | ||
*/ | ||
export const BqTsansacaoTipoIntegracaoMap = { | ||
3: 'Bu municipal', | ||
2: 'Integração', | ||
1: 'Transferência', | ||
0: 'Sem integração', | ||
4: 'Bu intermunicipal', | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/** | ||
* Ticket revenues payment type map | ||
*/ | ||
export const BqTransacaoTipoPagamentoMap = { | ||
1: 'Cartão', | ||
2: 'QRCode', | ||
3: 'NFC', | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/** | ||
* Ticket revenues transaction type map | ||
* | ||
* Business rules: | ||
* - "Integral" = Débito + Botoeria (both are considered "Integral" type). | ||
* See {@link https://github.com/RJ-SMTR/api-cct/issues/177#issuecomment-1934531824 Issue #177, item 1 - GitHub} | ||
* | ||
* Matching id or literal values. | ||
* See {@link https://github.com/RJ-SMTR/api-cct/issues/168#issuecomment-1900546567 Issue #168 - GitHub} | ||
*/ | ||
export const BqTransacaoTipoTransacaoMap = { | ||
/** Originally 1 = Débito */ | ||
1: 'Integral', | ||
2: 'Recarga', | ||
98: 'Riocard', | ||
6: 'Bloqueio', | ||
/** Originally 99 = Botoeria */ | ||
99: 'Integral', | ||
21: 'Gratuidade', | ||
3: 'Cancelamento', | ||
4: 'Integração', | ||
Débito: 'Integral', | ||
/** Botoeria = payment in cash */ | ||
Botoeria: 'Integral', | ||
}; |
228 changes: 228 additions & 0 deletions
228
src/bigquery/repositories/bq-transacao.repository.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,228 @@ | ||
import { Injectable, Logger } from '@nestjs/common'; | ||
import { BQSInstances, BigqueryService } from '../bigquery.service'; | ||
import { BqTransacao } from '../entities/transacao.bq-entity'; | ||
import { IBqFetchTransacao } from '../interfaces/bq-find-transacao-by.interface'; | ||
import { SettingsService } from 'src/settings/settings.service'; | ||
import { appSettings } from 'src/settings/app.settings'; | ||
import { BigqueryEnvironment } from 'src/settings/enums/bigquery-env.enum'; | ||
import { QueryBuilder } from 'src/utils/query-builder/query-builder'; | ||
import { isCpfOrCnpj } from 'src/utils/cpf-cnpj'; | ||
import { TRIntegrationTypeMap } from 'src/ticket-revenues/maps/ticket-revenues.map'; | ||
import { BqTsansacaoTipoIntegracaoMap } from '../maps/bq-transacao-tipo-integracao.map'; | ||
import { BqTransacaoTipoTransacaoMap } from '../maps/bq-transacao-tipo-transacao.map'; | ||
import { BqTransacaoTipoPagamentoMap } from '../maps/bq-transacao-tipo-pagamento.map'; | ||
|
||
@Injectable() | ||
export class BqTransacaoRepositoryService { | ||
private logger: Logger = new Logger('BqTransacaoRepositoryService', { | ||
timestamp: true, | ||
}); | ||
|
||
constructor( | ||
private readonly bigqueryService: BigqueryService, | ||
private readonly settingsService: SettingsService, | ||
) {} | ||
|
||
public async findTransacaoBy( | ||
filter?: IBqFetchTransacao, | ||
): Promise<BqTransacao[]> { | ||
const transacoes: BqTransacao[] = (await this.fetchTransacao(filter)).data; | ||
return transacoes; | ||
} | ||
|
||
private async fetchTransacao( | ||
args?: IBqFetchTransacao, | ||
): Promise<{ data: BqTransacao[]; countAll: number }> { | ||
const qArgs = await this.getQueryArgs(args); | ||
const query = | ||
` | ||
SELECT | ||
CAST(t.data AS STRING) AS partitionDate, | ||
t.hora AS processingHour, | ||
CAST(t.datetime_transacao AS STRING) AS datetime_transacao, | ||
CAST(t.datetime_processamento AS STRING) AS datetime_processamento, | ||
t.datetime_captura AS captureDateTime, | ||
t.modo AS modo, | ||
t.servico AS servico, | ||
t.sentido AS sentido, | ||
t.id_veiculo AS id_veiculo, | ||
t.id_cliente AS id_cliente, | ||
t.id_transacao AS id_transacao, | ||
t.${qArgs.tTipoPgto} AS tipo_pagamento, | ||
t.tipo_transacao AS tipo_transacao, | ||
t.id_tipo_integracao AS id_tipo_integracao, | ||
t.id_integracao AS id_integracao, | ||
t.latitude AS latitude, | ||
t.longitude AS longitude, | ||
t.stop_id AS stop_id, | ||
t.stop_lat AS stop_lat, | ||
t.stop_lon AS stop_lon, | ||
CASE WHEN t.tipo_transacao = 'Integração' THEN i.valor_transacao_total ELSE t.valor_transacao END AS valor_transacao, | ||
t.versao AS bqDataVersion, | ||
(${qArgs.countQuery}) AS count, | ||
'ok' AS status | ||
FROM \`${qArgs.transacao}\` t\n` + | ||
qArgs.joinCpfCnpj + | ||
'\n' + | ||
qArgs.joinIntegracao + | ||
'\n' + | ||
(qArgs.qWhere.length ? `WHERE ${qArgs.qWhere}\n` : '') + | ||
`UNION ALL | ||
SELECT ${'null, '.repeat(22)} | ||
(${qArgs.countQuery}) AS count, 'empty' AS status` + | ||
`\nORDER BY t.data DESC, t.hora DESC` + | ||
(qArgs?.limit !== undefined ? `\nLIMIT ${qArgs.limit + 1}` : '') + | ||
(qArgs?.offset !== undefined ? `\nOFFSET ${qArgs.offset}` : ''); | ||
const queryResult = await this.bigqueryService.query( | ||
BQSInstances.smtr, | ||
query, | ||
); | ||
|
||
const count: number = queryResult[0].count; | ||
// Remove unwanted keys and remove last item (all null if empty) | ||
let transacoes: BqTransacao[] = queryResult.map((i) => { | ||
delete i.status; | ||
delete i.count; | ||
return i; | ||
}); | ||
transacoes.pop(); | ||
transacoes = this.mapBqTransacao(transacoes); | ||
|
||
return { | ||
data: transacoes, | ||
countAll: count, | ||
}; | ||
} | ||
|
||
private async getQueryArgs(args?: IBqFetchTransacao): Promise<{ | ||
qWhere: string; | ||
bucket: string; | ||
transacao: string; | ||
integracao: string; | ||
tTipoPgto: string; | ||
joinCpfCnpj: string; | ||
joinIntegracao: string; | ||
countQuery: string; | ||
offset?: number; | ||
limit?: number; | ||
}> { | ||
const IS_BQ_PROD = | ||
( | ||
await this.settingsService.getOneBySettingData( | ||
appSettings.any__bigquery_env, | ||
true, | ||
) | ||
).getValueAsString() === BigqueryEnvironment.Production; | ||
const Q_CONSTS = { | ||
bucket: IS_BQ_PROD ? 'rj-smtr' : 'rj-smtr-dev', | ||
transacao: IS_BQ_PROD | ||
? 'rj-smtr.br_rj_riodejaneiro_bilhetagem.transacao' | ||
: 'rj-smtr-dev.br_rj_riodejaneiro_bilhetagem_cct.transacao', | ||
integracao: IS_BQ_PROD | ||
? 'rj-smtr.br_rj_riodejaneiro_bilhetagem.integracao' | ||
: 'rj-smtr-dev.br_rj_riodejaneiro_bilhetagem_cct.integracao', | ||
tTipoPgto: IS_BQ_PROD ? 'tipo_pagamento' : 'id_tipo_pagamento', | ||
}; | ||
// Args | ||
let offset = args?.offset; | ||
const queryBuilder = new QueryBuilder(); | ||
queryBuilder.pushOR([]); | ||
if (args?.offset !== undefined && args.limit === undefined) { | ||
this.logger.warn( | ||
"fetchTicketRevenues(): 'offset' is defined but 'limit' is not." + | ||
" 'offset' will be ignored to prevent query fail", | ||
); | ||
offset = undefined; | ||
} | ||
|
||
if (args?.startDate) { | ||
const startDate = args.startDate.toISOString().slice(0, 10); | ||
queryBuilder.pushAND( | ||
`DATE(t.datetime_processamento) >= DATE('${startDate}')`, | ||
); | ||
} | ||
if (args?.endDate) { | ||
const endDate = args.endDate.toISOString().slice(0, 10); | ||
queryBuilder.pushAND( | ||
`DATE(t.datetime_processamento) <= DATE('${endDate}')`, | ||
); | ||
} | ||
if (args?.previousDays === true) { | ||
queryBuilder.pushAND( | ||
'DATE(t.datetime_processamento) > DATE(t.datetime_transacao)', | ||
); | ||
} | ||
|
||
queryBuilder.pushOR([]); | ||
if (args?.getToday) { | ||
const nowStr = new Date(Date.now()).toISOString().slice(0, 10); | ||
queryBuilder.pushAND( | ||
`DATE(t.datetime_processamento) = DATE('${nowStr}')`, | ||
); | ||
} | ||
|
||
let qWhere = queryBuilder.toSQL(); | ||
if (args?.cpfCnpj !== undefined) { | ||
const cpfCnpj = args.cpfCnpj; | ||
qWhere = | ||
isCpfOrCnpj(args?.cpfCnpj) === 'cpf' | ||
? `b.documento = '${cpfCnpj}' AND (${qWhere})` | ||
: `b.cnpj = '${cpfCnpj}' AND (${qWhere})`; | ||
} | ||
|
||
// Query | ||
const joinCpfCnpj = | ||
isCpfOrCnpj(args?.cpfCnpj) === 'cpf' | ||
? `LEFT JOIN \`${Q_CONSTS.bucket}.cadastro.operadoras\` b ON b.id_operadora = t.id_operadora ` | ||
: `LEFT JOIN \`${Q_CONSTS.bucket}.cadastro.consorcios\` b ON b.id_consorcio = t.id_consorcio `; | ||
const joinIntegracao = `INNER JOIN ${Q_CONSTS.integracao} i ON i.id_transacao = t.id_transacao`; | ||
|
||
const countQuery = | ||
'SELECT COUNT(*) AS count ' + | ||
`FROM \`${Q_CONSTS.transacao}\` t\n` + | ||
joinCpfCnpj + | ||
'\n' + | ||
joinIntegracao + | ||
'\n' + | ||
(qWhere.length ? ` WHERE ${qWhere}\n` : ''); | ||
return { | ||
qWhere, | ||
bucket: Q_CONSTS.bucket, | ||
transacao: Q_CONSTS.transacao, | ||
integracao: Q_CONSTS.integracao, | ||
tTipoPgto: Q_CONSTS.tTipoPgto, | ||
joinCpfCnpj, | ||
joinIntegracao, | ||
countQuery, | ||
offset, | ||
limit: args?.limit, | ||
}; | ||
} | ||
|
||
/** | ||
* Convert id or some values into desired string values | ||
*/ | ||
private mapBqTransacao(transacoes: BqTransacao[]): BqTransacao[] { | ||
return transacoes.map((item: BqTransacao) => { | ||
const tipo_transacao = item.tipo_transacao; | ||
const tipo_pagamento = item.tipo_pagamento; | ||
const tipo_integracao = item.tipo_integracao; | ||
Object.values(TRIntegrationTypeMap[0]); | ||
return { | ||
...item, | ||
paymentMediaType: | ||
tipo_pagamento !== null | ||
? BqTransacaoTipoPagamentoMap?.[tipo_pagamento] || tipo_pagamento | ||
: tipo_pagamento, | ||
transportIntegrationType: | ||
tipo_integracao !== null | ||
? BqTsansacaoTipoIntegracaoMap?.[tipo_integracao] || tipo_integracao | ||
: tipo_integracao, | ||
transactionType: | ||
tipo_transacao !== null | ||
? BqTransacaoTipoTransacaoMap?.[tipo_transacao] || tipo_transacao | ||
: tipo_transacao, | ||
}; | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { EntityHelper } from '../../utils/entity-helper'; | ||
|
||
@Entity() | ||
export class DetalheA extends EntityHelper { | ||
id_detalhe_a: number; | ||
id_header_lote: number; | ||
lote_servico: string; | ||
id_cliente_favorecido: number; | ||
tipo_finalidade_conta: string; | ||
dt_vencimento: Date; | ||
tipo_moeda: string; | ||
qtde_moeda: number; | ||
valor_lancamento: number; | ||
num_doc_lancamento: string; | ||
qtde_parcelas: number; | ||
indicador_bloqueio: string; | ||
indicador_forma_parcelamento: string; | ||
periodo_vencimento: Date; | ||
num_parcela: number; | ||
data_efetivacao: Date; | ||
valor_real_efetivado: number; | ||
} | ||
|
||
function Entity(): (target: typeof DetalheA) => void | typeof DetalheA { | ||
throw new Error('Function not implemented.'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { EntityHelper } from 'src/utils/entity-helper'; | ||
|
||
@Entity() | ||
export class DetalheB extends EntityHelper { | ||
id_detalhe_b: number; | ||
id_detalhe_a: number; | ||
nsr: string; | ||
data_vencimento: Date; | ||
} | ||
|
||
function Entity(): (target: typeof DetalheB) => void | typeof DetalheB { | ||
throw new Error('Function not implemented.'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { EntityHelper } from 'src/utils/entity-helper'; | ||
|
||
@Entity() | ||
export class HeaderArquivo extends EntityHelper { | ||
id_header_arquivo: number; | ||
tipo_arquivo: string; | ||
cod_banco: string; | ||
tipo_inscricao: string; | ||
num_inscricao: string; | ||
cod_convenio: string; | ||
param_transmissao: string; | ||
agencia: string; | ||
dv_agencia: string; | ||
num_conta: string; | ||
dv_conta: string; | ||
nome_empresa: string; | ||
dt_geracao: Date; | ||
hr_geracao: Date; | ||
id_transacao: number; | ||
} | ||
|
||
function Entity(): ( | ||
target: typeof HeaderArquivo, | ||
) => void | typeof HeaderArquivo { | ||
throw new Error('Function not implemented.'); | ||
} |
Oops, something went wrong.