feat(investment): Daily Script Master backend
Market rate of each script for a day (open / high / low / close), as the bank's existing CBS keeps it, so Purchase Entry can take its rate from here instead of the dealer typing it (Jitendra Sir). - m_investment_daily_rate, one row per script per day (migration 0596), with READ/CREATE/DELETE permissions granted to Investment menu roles. - /v1/investment/daily-rates: list (optionally per script), save, drop, and /latest for the newest rate of a script on or before a date. - Close rate is mandatory; high may not be below low, and open / close must sit inside low-high, with readable messages. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+16
@@ -151,6 +151,22 @@ public class CommandWrapperBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CommandWrapperBuilder createInvestmentDailyRate() {
|
||||||
|
this.actionName = "CREATE";
|
||||||
|
this.entityName = "INVESTMENTDAILYRATE";
|
||||||
|
this.entityId = null;
|
||||||
|
this.href = "/investment/daily-rates";
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandWrapperBuilder deleteInvestmentDailyRate(final Long rateId) {
|
||||||
|
this.actionName = "DELETE";
|
||||||
|
this.entityName = "INVESTMENTDAILYRATE";
|
||||||
|
this.entityId = rateId;
|
||||||
|
this.href = "/investment/daily-rates/" + rateId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public CommandWrapperBuilder createChequeStockLot() {
|
public CommandWrapperBuilder createChequeStockLot() {
|
||||||
this.actionName = "CREATE";
|
this.actionName = "CREATE";
|
||||||
this.entityName = "CHEQUESTOCKLOT";
|
this.entityName = "CHEQUESTOCKLOT";
|
||||||
|
|||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.investment.api;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/** Constants for the Daily Script Master (market rate of a script for a day). */
|
||||||
|
public final class InvestmentDailyRateApiConstants {
|
||||||
|
|
||||||
|
private InvestmentDailyRateApiConstants() {}
|
||||||
|
|
||||||
|
public static final String ENTITY = "INVESTMENTDAILYRATE";
|
||||||
|
public static final String RESOURCE = "investmentdailyrate";
|
||||||
|
|
||||||
|
public static final String SCRIPT_ID = "scriptId";
|
||||||
|
public static final String RATE_DATE = "rateDate";
|
||||||
|
public static final String OPEN_RATE = "openRate";
|
||||||
|
public static final String HIGH_RATE = "highRate";
|
||||||
|
public static final String LOW_RATE = "lowRate";
|
||||||
|
public static final String CLOSE_RATE = "closeRate";
|
||||||
|
public static final String LOCALE = "locale";
|
||||||
|
public static final String DATE_FORMAT = "dateFormat";
|
||||||
|
|
||||||
|
public static final Set<String> PARAMS = Set.of(SCRIPT_ID, RATE_DATE, OPEN_RATE, HIGH_RATE, LOW_RATE, CLOSE_RATE, LOCALE, DATE_FORMAT);
|
||||||
|
}
|
||||||
+96
@@ -0,0 +1,96 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.investment.api;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.ws.rs.Consumes;
|
||||||
|
import jakarta.ws.rs.DELETE;
|
||||||
|
import jakarta.ws.rs.GET;
|
||||||
|
import jakarta.ws.rs.POST;
|
||||||
|
import jakarta.ws.rs.Path;
|
||||||
|
import jakarta.ws.rs.PathParam;
|
||||||
|
import jakarta.ws.rs.Produces;
|
||||||
|
import jakarta.ws.rs.QueryParam;
|
||||||
|
import jakarta.ws.rs.core.MediaType;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||||
|
import org.apache.fineract.commands.service.CommandWrapperBuilder;
|
||||||
|
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||||
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
|
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||||
|
import org.apache.fineract.portfolio.investment.data.InvestmentDailyRateData;
|
||||||
|
import org.apache.fineract.portfolio.investment.service.InvestmentDailyRateReadPlatformService;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Path("/v1/investment/daily-rates")
|
||||||
|
@Component
|
||||||
|
@Tag(name = "Investment Daily Script Master", description = "Market rate of each script for a day; Purchase Entry takes its rate from here.")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class InvestmentDailyRateApiResource {
|
||||||
|
|
||||||
|
private final PlatformSecurityContext context;
|
||||||
|
private final InvestmentDailyRateReadPlatformService readPlatformService;
|
||||||
|
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
|
@Operation(summary = "List daily script rates, newest first")
|
||||||
|
public List<InvestmentDailyRateData> retrieveAll(@QueryParam("scriptId") @Parameter(description = "scriptId") final Long scriptId) {
|
||||||
|
this.context.authenticatedUser().validateHasReadPermission(InvestmentDailyRateApiConstants.ENTITY);
|
||||||
|
return this.readPlatformService.retrieveAll(scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("latest")
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
|
@Operation(summary = "Newest rate of a script on or before a date", description = "onDate (dd-MM-yyyy) defaults to the business "
|
||||||
|
+ "date. Returns no content when no rate has been entered for the script.")
|
||||||
|
public InvestmentDailyRateData retrieveLatest(@QueryParam("scriptId") @Parameter(description = "scriptId") final Long scriptId,
|
||||||
|
@QueryParam("onDate") @Parameter(description = "dd-MM-yyyy") final String onDate) {
|
||||||
|
this.context.authenticatedUser().validateHasReadPermission(InvestmentDailyRateApiConstants.ENTITY);
|
||||||
|
final LocalDate on = StringUtils.isBlank(onDate) ? DateUtils.getBusinessLocalDate()
|
||||||
|
: LocalDate.parse(onDate.trim(), DateTimeFormatter.ofPattern("dd-MM-yyyy"));
|
||||||
|
return this.readPlatformService.retrieveLatest(scriptId, on);
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Consumes({ MediaType.APPLICATION_JSON })
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
|
@Operation(summary = "Save a daily script rate")
|
||||||
|
public CommandProcessingResult create(@Parameter(hidden = true) final String apiRequestBodyAsJson) {
|
||||||
|
final CommandWrapper request = new CommandWrapperBuilder().createInvestmentDailyRate().withJson(apiRequestBodyAsJson).build();
|
||||||
|
return this.commandsSourceWritePlatformService.logCommandSource(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DELETE
|
||||||
|
@Path("{rateId}")
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
|
@Operation(summary = "Drop a daily script rate")
|
||||||
|
public CommandProcessingResult delete(@PathParam("rateId") @Parameter(description = "rateId") final Long rateId) {
|
||||||
|
final CommandWrapper request = new CommandWrapperBuilder().deleteInvestmentDailyRate(rateId).build();
|
||||||
|
return this.commandsSourceWritePlatformService.logCommandSource(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
+50
@@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.investment.data;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.apache.fineract.portfolio.investment.domain.InvestmentDailyRate;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Builder
|
||||||
|
public class InvestmentDailyRateData {
|
||||||
|
|
||||||
|
private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("dd-MM-yyyy");
|
||||||
|
|
||||||
|
private final Long id;
|
||||||
|
private final Long scriptId;
|
||||||
|
private final String scriptCode;
|
||||||
|
private final String scriptDesc;
|
||||||
|
private final String bondType;
|
||||||
|
private final String rateDate;
|
||||||
|
private final BigDecimal openRate;
|
||||||
|
private final BigDecimal highRate;
|
||||||
|
private final BigDecimal lowRate;
|
||||||
|
private final BigDecimal closeRate;
|
||||||
|
|
||||||
|
public static InvestmentDailyRateData from(final InvestmentDailyRate r) {
|
||||||
|
return InvestmentDailyRateData.builder().id(r.getId()).scriptId(r.getScript().getId()).scriptCode(r.getScript().getScriptCode())
|
||||||
|
.scriptDesc(r.getScript().getScriptDesc()).bondType(r.getScript().getBondType())
|
||||||
|
.rateDate(r.getRateDate().format(DATE_FORMAT)).openRate(r.getOpenRate()).highRate(r.getHighRate()).lowRate(r.getLowRate())
|
||||||
|
.closeRate(r.getCloseRate()).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
+62
@@ -0,0 +1,62 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.investment.domain;
|
||||||
|
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.JoinColumn;
|
||||||
|
import jakarta.persistence.ManyToOne;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Daily Script Master: the market rate of a script for one day, as the bank's existing CBS keeps it. Purchase Entry
|
||||||
|
* takes its rate from here (Jitendra Sir). Close rate is mandatory; open, high and low are optional.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "m_investment_daily_rate")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class InvestmentDailyRate extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "script_id", nullable = false)
|
||||||
|
private InvestmentScript script;
|
||||||
|
|
||||||
|
@Column(name = "rate_date", nullable = false)
|
||||||
|
private LocalDate rateDate;
|
||||||
|
|
||||||
|
@Column(name = "open_rate", scale = 6, precision = 19)
|
||||||
|
private BigDecimal openRate;
|
||||||
|
|
||||||
|
@Column(name = "high_rate", scale = 6, precision = 19)
|
||||||
|
private BigDecimal highRate;
|
||||||
|
|
||||||
|
@Column(name = "low_rate", scale = 6, precision = 19)
|
||||||
|
private BigDecimal lowRate;
|
||||||
|
|
||||||
|
@Column(name = "close_rate", scale = 6, precision = 19, nullable = false)
|
||||||
|
private BigDecimal closeRate;
|
||||||
|
}
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.investment.domain;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface InvestmentDailyRateRepository extends JpaRepository<InvestmentDailyRate, Long> {
|
||||||
|
|
||||||
|
boolean existsByScriptIdAndRateDate(Long scriptId, LocalDate rateDate);
|
||||||
|
|
||||||
|
/** The newest rate of a script on or before a date. */
|
||||||
|
Optional<InvestmentDailyRate> findFirstByScriptIdAndRateDateLessThanEqualOrderByRateDateDesc(Long scriptId, LocalDate onDate);
|
||||||
|
|
||||||
|
List<InvestmentDailyRate> findByScriptIdOrderByRateDateDesc(Long scriptId);
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.investment.exception;
|
||||||
|
|
||||||
|
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||||
|
|
||||||
|
public class InvestmentDailyRateNotFoundException extends AbstractPlatformResourceNotFoundException {
|
||||||
|
|
||||||
|
public InvestmentDailyRateNotFoundException(final Long id) {
|
||||||
|
super("error.msg.investmentdailyrate.id.invalid", "Daily script rate with identifier " + id + " does not exist", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.investment.handler;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.fineract.commands.annotation.CommandType;
|
||||||
|
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||||
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
import org.apache.fineract.portfolio.investment.service.InvestmentDailyRateWritePlatformService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@CommandType(entity = "INVESTMENTDAILYRATE", action = "CREATE")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CreateInvestmentDailyRateCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
|
private final InvestmentDailyRateWritePlatformService writePlatformService;
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
|
return this.writePlatformService.createDailyRate(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.investment.handler;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.fineract.commands.annotation.CommandType;
|
||||||
|
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||||
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
import org.apache.fineract.portfolio.investment.service.InvestmentDailyRateWritePlatformService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@CommandType(entity = "INVESTMENTDAILYRATE", action = "DELETE")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class DeleteInvestmentDailyRateCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
|
private final InvestmentDailyRateWritePlatformService writePlatformService;
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
|
return this.writePlatformService.deleteDailyRate(command.entityId());
|
||||||
|
}
|
||||||
|
}
|
||||||
+103
@@ -0,0 +1,103 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.investment.serialization;
|
||||||
|
|
||||||
|
import static org.apache.fineract.portfolio.investment.api.InvestmentDailyRateApiConstants.CLOSE_RATE;
|
||||||
|
import static org.apache.fineract.portfolio.investment.api.InvestmentDailyRateApiConstants.HIGH_RATE;
|
||||||
|
import static org.apache.fineract.portfolio.investment.api.InvestmentDailyRateApiConstants.LOW_RATE;
|
||||||
|
import static org.apache.fineract.portfolio.investment.api.InvestmentDailyRateApiConstants.OPEN_RATE;
|
||||||
|
import static org.apache.fineract.portfolio.investment.api.InvestmentDailyRateApiConstants.PARAMS;
|
||||||
|
import static org.apache.fineract.portfolio.investment.api.InvestmentDailyRateApiConstants.RATE_DATE;
|
||||||
|
import static org.apache.fineract.portfolio.investment.api.InvestmentDailyRateApiConstants.RESOURCE;
|
||||||
|
import static org.apache.fineract.portfolio.investment.api.InvestmentDailyRateApiConstants.SCRIPT_ID;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||||
|
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||||
|
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
|
||||||
|
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||||
|
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/** Validates a Daily Script Master entry: close rate is mandatory and the day's rates must sit inside low to high. */
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public final class InvestmentDailyRateCommandFromApiJsonDeserializer {
|
||||||
|
|
||||||
|
private final FromJsonHelper fromApiJsonHelper;
|
||||||
|
|
||||||
|
public void validateForCreate(final String json) {
|
||||||
|
if (StringUtils.isBlank(json)) {
|
||||||
|
throw new InvalidJsonException();
|
||||||
|
}
|
||||||
|
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||||
|
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, PARAMS);
|
||||||
|
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||||
|
|
||||||
|
final List<ApiParameterError> errors = new ArrayList<>();
|
||||||
|
final DataValidatorBuilder v = new DataValidatorBuilder(errors).resource(RESOURCE);
|
||||||
|
|
||||||
|
v.reset().parameter(SCRIPT_ID).value(this.fromApiJsonHelper.extractLongNamed(SCRIPT_ID, element)).notNull().longGreaterThanZero();
|
||||||
|
v.reset().parameter(RATE_DATE).value(this.fromApiJsonHelper.extractLocalDateNamed(RATE_DATE, element)).notNull();
|
||||||
|
final BigDecimal close = amount(CLOSE_RATE, element);
|
||||||
|
final BigDecimal open = amount(OPEN_RATE, element);
|
||||||
|
final BigDecimal high = amount(HIGH_RATE, element);
|
||||||
|
final BigDecimal low = amount(LOW_RATE, element);
|
||||||
|
v.reset().parameter(CLOSE_RATE).value(close).notNull().positiveAmount();
|
||||||
|
v.reset().parameter(OPEN_RATE).value(open).ignoreIfNull().positiveAmount();
|
||||||
|
v.reset().parameter(HIGH_RATE).value(high).ignoreIfNull().positiveAmount();
|
||||||
|
v.reset().parameter(LOW_RATE).value(low).ignoreIfNull().positiveAmount();
|
||||||
|
|
||||||
|
if (high != null && low != null && high.compareTo(low) < 0) {
|
||||||
|
v.reset().parameter(HIGH_RATE).failWithCodeAndMessage("less.than.low.rate", "High Rate cannot be below Low Rate");
|
||||||
|
}
|
||||||
|
outsideRange(v, CLOSE_RATE, "Close Rate", close, low, high);
|
||||||
|
outsideRange(v, OPEN_RATE, "Open Rate", open, low, high);
|
||||||
|
|
||||||
|
if (!errors.isEmpty()) {
|
||||||
|
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void outsideRange(final DataValidatorBuilder v, final String param, final String label, final BigDecimal rate,
|
||||||
|
final BigDecimal low, final BigDecimal high) {
|
||||||
|
if (rate == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (low != null && rate.compareTo(low) < 0) {
|
||||||
|
v.reset().parameter(param).failWithCodeAndMessage("below.low.rate", label + " cannot be below Low Rate");
|
||||||
|
} else if (high != null && rate.compareTo(high) > 0) {
|
||||||
|
v.reset().parameter(param).failWithCodeAndMessage("above.high.rate", label + " cannot be above High Rate");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal amount(final String param, final JsonElement element) {
|
||||||
|
return this.fromApiJsonHelper.parameterExists(param, element)
|
||||||
|
? this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(param, element)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
}
|
||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.investment.service;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.fineract.portfolio.investment.data.InvestmentDailyRateData;
|
||||||
|
import org.apache.fineract.portfolio.investment.domain.InvestmentDailyRateRepository;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public class InvestmentDailyRateReadPlatformService {
|
||||||
|
|
||||||
|
/** The register shows the latest rates first; older ones are reached by picking a script. */
|
||||||
|
private static final int MAX_ROWS = 500;
|
||||||
|
|
||||||
|
private final InvestmentDailyRateRepository dailyRateRepository;
|
||||||
|
|
||||||
|
public List<InvestmentDailyRateData> retrieveAll(final Long scriptId) {
|
||||||
|
if (scriptId != null) {
|
||||||
|
return this.dailyRateRepository.findByScriptIdOrderByRateDateDesc(scriptId).stream().map(InvestmentDailyRateData::from)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
return this.dailyRateRepository
|
||||||
|
.findAll(PageRequest.of(0, MAX_ROWS, Sort.by(Sort.Direction.DESC, "rateDate").and(Sort.by(Sort.Direction.DESC, "id"))))
|
||||||
|
.stream().map(InvestmentDailyRateData::from).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The newest rate of a script on or before {@code onDate}; null when none has been entered. */
|
||||||
|
public InvestmentDailyRateData retrieveLatest(final Long scriptId, final LocalDate onDate) {
|
||||||
|
return this.dailyRateRepository.findFirstByScriptIdAndRateDateLessThanEqualOrderByRateDateDesc(scriptId, onDate)
|
||||||
|
.map(InvestmentDailyRateData::from).orElse(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.investment.service;
|
||||||
|
|
||||||
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
|
||||||
|
public interface InvestmentDailyRateWritePlatformService {
|
||||||
|
|
||||||
|
CommandProcessingResult createDailyRate(JsonCommand command);
|
||||||
|
|
||||||
|
CommandProcessingResult deleteDailyRate(Long rateId);
|
||||||
|
}
|
||||||
+87
@@ -0,0 +1,87 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.fineract.portfolio.investment.service;
|
||||||
|
|
||||||
|
import static org.apache.fineract.portfolio.investment.api.InvestmentDailyRateApiConstants.CLOSE_RATE;
|
||||||
|
import static org.apache.fineract.portfolio.investment.api.InvestmentDailyRateApiConstants.HIGH_RATE;
|
||||||
|
import static org.apache.fineract.portfolio.investment.api.InvestmentDailyRateApiConstants.LOW_RATE;
|
||||||
|
import static org.apache.fineract.portfolio.investment.api.InvestmentDailyRateApiConstants.OPEN_RATE;
|
||||||
|
import static org.apache.fineract.portfolio.investment.api.InvestmentDailyRateApiConstants.RATE_DATE;
|
||||||
|
import static org.apache.fineract.portfolio.investment.api.InvestmentDailyRateApiConstants.SCRIPT_ID;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||||
|
import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
|
||||||
|
import org.apache.fineract.portfolio.investment.domain.InvestmentDailyRate;
|
||||||
|
import org.apache.fineract.portfolio.investment.domain.InvestmentDailyRateRepository;
|
||||||
|
import org.apache.fineract.portfolio.investment.domain.InvestmentScript;
|
||||||
|
import org.apache.fineract.portfolio.investment.domain.InvestmentScriptRepository;
|
||||||
|
import org.apache.fineract.portfolio.investment.exception.InvestmentDailyRateNotFoundException;
|
||||||
|
import org.apache.fineract.portfolio.investment.exception.InvestmentScriptNotFoundException;
|
||||||
|
import org.apache.fineract.portfolio.investment.serialization.InvestmentDailyRateCommandFromApiJsonDeserializer;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
/** Saves and drops Daily Script Master rates. A wrong rate is corrected by dropping it and entering it again. */
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class InvestmentDailyRateWritePlatformServiceImpl implements InvestmentDailyRateWritePlatformService {
|
||||||
|
|
||||||
|
private final InvestmentDailyRateCommandFromApiJsonDeserializer validator;
|
||||||
|
private final InvestmentDailyRateRepository dailyRateRepository;
|
||||||
|
private final InvestmentScriptRepository scriptRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public CommandProcessingResult createDailyRate(final JsonCommand command) {
|
||||||
|
this.validator.validateForCreate(command.json());
|
||||||
|
final Long scriptId = command.longValueOfParameterNamed(SCRIPT_ID);
|
||||||
|
final InvestmentScript script = this.scriptRepository.findById(scriptId)
|
||||||
|
.orElseThrow(() -> new InvestmentScriptNotFoundException(scriptId));
|
||||||
|
final LocalDate rateDate = command.localDateValueOfParameterNamed(RATE_DATE);
|
||||||
|
if (this.dailyRateRepository.existsByScriptIdAndRateDate(scriptId, rateDate)) {
|
||||||
|
throw new GeneralPlatformDomainRuleException("error.msg.investmentdailyrate.duplicate",
|
||||||
|
"A rate for " + script.getScriptCode() + " on this date already exists. Drop it first to correct it.");
|
||||||
|
}
|
||||||
|
|
||||||
|
final InvestmentDailyRate rate = new InvestmentDailyRate();
|
||||||
|
rate.setScript(script);
|
||||||
|
rate.setRateDate(rateDate);
|
||||||
|
rate.setOpenRate(command.bigDecimalValueOfParameterNamed(OPEN_RATE));
|
||||||
|
rate.setHighRate(command.bigDecimalValueOfParameterNamed(HIGH_RATE));
|
||||||
|
rate.setLowRate(command.bigDecimalValueOfParameterNamed(LOW_RATE));
|
||||||
|
rate.setCloseRate(command.bigDecimalValueOfParameterNamed(CLOSE_RATE));
|
||||||
|
final InvestmentDailyRate saved = this.dailyRateRepository.saveAndFlush(rate);
|
||||||
|
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(saved.getId())
|
||||||
|
.withResourceIdAsString(script.getScriptCode()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public CommandProcessingResult deleteDailyRate(final Long rateId) {
|
||||||
|
final InvestmentDailyRate rate = this.dailyRateRepository.findById(rateId)
|
||||||
|
.orElseThrow(() -> new InvestmentDailyRateNotFoundException(rateId));
|
||||||
|
this.dailyRateRepository.delete(rate);
|
||||||
|
this.dailyRateRepository.flush();
|
||||||
|
return new CommandProcessingResultBuilder().withEntityId(rateId).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -170,4 +170,5 @@
|
|||||||
<include file="parts/0593_investment_masters.xml" relativeToChangelogFile="true"/>
|
<include file="parts/0593_investment_masters.xml" relativeToChangelogFile="true"/>
|
||||||
<include file="parts/0594_investment_purchase.xml" relativeToChangelogFile="true"/>
|
<include file="parts/0594_investment_purchase.xml" relativeToChangelogFile="true"/>
|
||||||
<include file="parts/0595_investment_purchase_other_charges.xml" relativeToChangelogFile="true"/>
|
<include file="parts/0595_investment_purchase_other_charges.xml" relativeToChangelogFile="true"/>
|
||||||
|
<include file="parts/0596_investment_daily_rate.xml" relativeToChangelogFile="true"/>
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
|
|||||||
+108
@@ -0,0 +1,108 @@
|
|||||||
|
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing,
|
||||||
|
software distributed under the License is distributed on an
|
||||||
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, either express or implied. See the License for the
|
||||||
|
specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.9.xsd">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Daily Script Master: the market rate of each script for a day (open / high / low / close),
|
||||||
|
entered by treasury from FBIL / CCIL. Purchase Entry takes its rate from here instead of the
|
||||||
|
dealer typing it (Jitendra Sir). One row per script per day.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<changeSet author="cbs-anshul" id="0596-1-create-investment-daily-rate">
|
||||||
|
<preConditions onFail="MARK_RAN">
|
||||||
|
<not><tableExists tableName="m_investment_daily_rate"/></not>
|
||||||
|
</preConditions>
|
||||||
|
<createTable tableName="m_investment_daily_rate">
|
||||||
|
<column name="id" type="BIGINT" autoIncrement="true"><constraints nullable="false" primaryKey="true"/></column>
|
||||||
|
<column name="script_id" type="BIGINT"><constraints nullable="false"/></column>
|
||||||
|
<column name="rate_date" type="DATE"><constraints nullable="false"/></column>
|
||||||
|
<column name="open_rate" type="DECIMAL(19,6)"/>
|
||||||
|
<column name="high_rate" type="DECIMAL(19,6)"/>
|
||||||
|
<column name="low_rate" type="DECIMAL(19,6)"/>
|
||||||
|
<column name="close_rate" type="DECIMAL(19,6)"><constraints nullable="false"/></column>
|
||||||
|
<column name="created_by" type="BIGINT"><constraints nullable="false"/></column>
|
||||||
|
<column name="created_on_utc" type="DATETIME"><constraints nullable="false"/></column>
|
||||||
|
<column name="last_modified_by" type="BIGINT"><constraints nullable="false"/></column>
|
||||||
|
<column name="last_modified_on_utc" type="DATETIME"><constraints nullable="false"/></column>
|
||||||
|
</createTable>
|
||||||
|
<addUniqueConstraint tableName="m_investment_daily_rate" columnNames="script_id, rate_date"
|
||||||
|
constraintName="uq_investment_daily_rate_script_date"/>
|
||||||
|
<addForeignKeyConstraint baseTableName="m_investment_daily_rate" baseColumnNames="script_id" constraintName="fk_investment_daily_rate_script"
|
||||||
|
referencedTableName="m_investment_script" referencedColumnNames="id"/>
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
<changeSet author="cbs-anshul" id="0596-2-investment-daily-rate-permissions">
|
||||||
|
<preConditions onFail="MARK_RAN">
|
||||||
|
<sqlCheck expectedResult="0">SELECT COUNT(*) FROM m_permission WHERE code IN ('READ_INVESTMENTDAILYRATE', 'CREATE_INVESTMENTDAILYRATE', 'DELETE_INVESTMENTDAILYRATE', 'CREATE_INVESTMENTDAILYRATE_CHECKER', 'DELETE_INVESTMENTDAILYRATE_CHECKER')</sqlCheck>
|
||||||
|
</preConditions>
|
||||||
|
<insert tableName="m_permission">
|
||||||
|
<column name="grouping" value="portfolio"/>
|
||||||
|
<column name="code" value="READ_INVESTMENTDAILYRATE"/>
|
||||||
|
<column name="entity_name" value="INVESTMENTDAILYRATE"/>
|
||||||
|
<column name="action_name" value="READ"/>
|
||||||
|
<column name="can_maker_checker" valueBoolean="false"/>
|
||||||
|
</insert>
|
||||||
|
<insert tableName="m_permission">
|
||||||
|
<column name="grouping" value="portfolio"/>
|
||||||
|
<column name="code" value="CREATE_INVESTMENTDAILYRATE"/>
|
||||||
|
<column name="entity_name" value="INVESTMENTDAILYRATE"/>
|
||||||
|
<column name="action_name" value="CREATE"/>
|
||||||
|
<column name="can_maker_checker" valueBoolean="false"/>
|
||||||
|
</insert>
|
||||||
|
<insert tableName="m_permission">
|
||||||
|
<column name="grouping" value="portfolio"/>
|
||||||
|
<column name="code" value="DELETE_INVESTMENTDAILYRATE"/>
|
||||||
|
<column name="entity_name" value="INVESTMENTDAILYRATE"/>
|
||||||
|
<column name="action_name" value="DELETE"/>
|
||||||
|
<column name="can_maker_checker" valueBoolean="false"/>
|
||||||
|
</insert>
|
||||||
|
<insert tableName="m_permission">
|
||||||
|
<column name="grouping" value="portfolio"/>
|
||||||
|
<column name="code" value="CREATE_INVESTMENTDAILYRATE_CHECKER"/>
|
||||||
|
<column name="entity_name" value="INVESTMENTDAILYRATE"/>
|
||||||
|
<column name="action_name" value="CREATE_CHECKER"/>
|
||||||
|
<column name="can_maker_checker" valueBoolean="false"/>
|
||||||
|
</insert>
|
||||||
|
<insert tableName="m_permission">
|
||||||
|
<column name="grouping" value="portfolio"/>
|
||||||
|
<column name="code" value="DELETE_INVESTMENTDAILYRATE_CHECKER"/>
|
||||||
|
<column name="entity_name" value="INVESTMENTDAILYRATE"/>
|
||||||
|
<column name="action_name" value="DELETE_CHECKER"/>
|
||||||
|
<column name="can_maker_checker" valueBoolean="false"/>
|
||||||
|
</insert>
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
<!-- Same roles as the other investment screens: whoever sees the Investment menu. -->
|
||||||
|
<changeSet author="cbs-anshul" id="0596-3-grant-investment-daily-rate-permissions">
|
||||||
|
<sql>
|
||||||
|
INSERT INTO m_role_permission (role_id, permission_id)
|
||||||
|
SELECT rp.role_id, p.id
|
||||||
|
FROM m_role_permission rp
|
||||||
|
JOIN m_permission menu ON menu.id = rp.permission_id AND menu.code = 'MENU_INVESTMENT'
|
||||||
|
CROSS JOIN m_permission p
|
||||||
|
WHERE p.code IN ('READ_INVESTMENTDAILYRATE', 'CREATE_INVESTMENTDAILYRATE', 'DELETE_INVESTMENTDAILYRATE')
|
||||||
|
AND NOT EXISTS (SELECT 1 FROM m_role_permission x WHERE x.role_id = rp.role_id AND x.permission_id = p.id)
|
||||||
|
</sql>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
||||||
Reference in New Issue
Block a user