updated code

This commit is contained in:
Mohd-Arham
2025-11-24 10:13:42 +05:30
12 changed files with 253 additions and 93 deletions
@@ -0,0 +1,15 @@
package com.billpaymentservice.bbps.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class BillerAdditonalInfoDTO {
private String paramConfigId;
private String paramName;
private String dataTypeDAO;
private String dataTypeModel;
private boolean optional;
private boolean visibility;
}
@@ -2,6 +2,7 @@ package com.billpaymentservice.bbps.dto;
import java.util.List;
import com.billpaymentservice.bbps.entites.AdditionalInfoBillValidate;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import jakarta.validation.constraints.NotBlank;
@@ -102,7 +103,7 @@ public class BillerDTO {
private BillerResponseParamsDTO billerResponseParams;
private List<AdditionalInfoDTO> billerAdditionalInfos;
private List<AdditionalInfoDTO> billerAdditionalInfoPayments;
private List<BillerAdditonalInfoDTO> billerAdditionalInfoPayments;
private List<InterchangeFeeConfDTO> interchangeFeeConves;
private List<InterchangeFeeDTO> interchangeFees;
@@ -19,7 +19,6 @@ import lombok.ToString;
@NoArgsConstructor
@ToString
public class FetchBillValidateResponse {
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private GeneralResp genericResponse;
private String billId;
@@ -0,0 +1,29 @@
package com.billpaymentservice.bbps.entites;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
@Entity
@Table(name = "additional_info_bill_validate")
@Getter
@Setter
public class AdditionalInfoBillValidate {
@Id
@GeneratedValue
private Long id;
private String name;
private String value;
// ✅ Many Params → One Bill
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "bill_id_fk")
private BillValidation bill;
}
@@ -37,8 +37,8 @@ public class BillValidation {
@Column(name = "biller_response", columnDefinition = "TEXT")
private String billerResponse;
@Column(name = "additional_info", columnDefinition = "TEXT")
private String additionalInfo;
@OneToMany(mappedBy = "bill", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<AdditionalInfoBillValidate> additionalInfo;
// 👇 Proper nested customer params (OneToMany)
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "bill")
@@ -0,0 +1,47 @@
package com.billpaymentservice.bbps.entites;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Table(name = "biller_additional_info_payment")
@Entity
public class BillerAdditionalInfoPayment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // primary key for the table
@Column(name = "param_config_id", nullable = false)
@NotBlank(message = "Param Config ID cannot be blank")
private String paramConfigId;
@Column(name = "param_name", nullable = false)
@NotBlank(message = "Param name cannot be blank")
private String paramName;
@Column(name = "data_type_dao")
private String dataTypeDAO;
@Column(name = "data_type_model")
private String dataTypeModel;
@Column(name = "optional", nullable = false)
private boolean optional;
@Column(name = "visibility", nullable = false)
private boolean visibility;
// 🔗 Many AdditionalInfos belong to one Biller
@ManyToOne
@JoinColumn(name = "biller_id", nullable = false)
private BillerDetails biller;
}
@@ -29,7 +29,8 @@ import lombok.ToString;
"billerAdditionalInfos",
"interchangeFeeConves",
"interchangeFees",
"billerPlanResponseParams"
"billerPlanResponseParams",
"billerAdditionalInfoPayments"
})
@Table(name = "biller_details")
@@ -151,11 +152,9 @@ public class BillerDetails {
@OneToMany(mappedBy = "biller", cascade = CascadeType.ALL, orphanRemoval = true)
private List<AdditionalInfo> billerAdditionalInfos;
/*
* OneToMany(mappedBy = "biller", cascade = CascadeType.ALL, orphanRemoval
* =true) private List<AdditionalInfo> billerAdditionalInfoPayments;
*/
@OneToMany(mappedBy = "biller", cascade = CascadeType.ALL, orphanRemoval=true)
private List<BillerAdditionalInfoPayment> billerAdditionalInfoPayments;
@OneToMany(mappedBy = "biller", cascade = CascadeType.ALL, orphanRemoval = true)
private List<InterchangeFeeConf> interchangeFeeConves;
@@ -75,8 +75,8 @@ public class AgentServiceImpl implements AgentService {
@Override
public ResponseModel initiateBillFetch(FetchBillRequest fetchBillRequest) {
LOGGER.info("Initiating bill fetch for request ID: {} and MID", fetchBillRequest.getReqId(),
fetchBillRequest.getMid());
LOGGER.info("Initiating bill fetch for request ID: {} and MID :{} and billerId:{} ", fetchBillRequest.getReqId(),
fetchBillRequest.getMid(),fetchBillRequest.getBillerId());
String apiName = "InitiateBillFetch";
String txnId = helper.generateTxnId(15);
String requestId = fetchBillRequest.getReqId();
@@ -223,64 +223,80 @@ public class AgentServiceImpl implements AgentService {
@Override
public ResponseModel fetchBillById(BillFetchByBillIdRequest billFetchByBillIdRequest) {
String apiName = "FetchBillById";
String txnId = helper.generateTxnId(15);
String reqId = billFetchByBillIdRequest.getReqId();
String billId = billFetchByBillIdRequest.getBillId();
String fullUrl = agentDtaUrl + BBPSConstant.BILL_FETCH_BY_ID + billFetchByBillIdRequest.getBillId();
String apiName = "FetchBillById";
String txnId = helper.generateTxnId(15);
String reqId = billFetchByBillIdRequest.getReqId();
String billId = billFetchByBillIdRequest.getBillId();
String fullUrl = agentDtaUrl + BBPSConstant.BILL_FETCH_BY_ID + billFetchByBillIdRequest.getBillId();
LOGGER.info("Initiating {} API for billId={} and reqId={}", apiName, billId, reqId);
LOGGER.info("Initiating {} API for billId={} and reqId={}", apiName, billId, reqId);
try {
helper.validateMerchant(billFetchByBillIdRequest.getMid());
LOGGER.debug("Merchant validated successfully for MID={}", billFetchByBillIdRequest.getMid());
// create inbound log (GET -> no request body)
InboundTraceLog inboundLog = helper.createInboundLog(reqId, txnId, apiName,
billFetchByBillIdRequest.getMid(), "GET", null);
BharatConnectMaster headersData = beneficiaryDetailsRepository.findByOrgId("ORG001");
HttpHeaders headers = new HttpHeaders();
headers.set("x-digiledge-key", headersData.getXDigiledgeKey());
headers.set("agentId", headersData.getAgentId());
headers.set("tenantId", headersData.getTenantId());
headers.setContentType(MediaType.APPLICATION_JSON);
try {
helper.validateMerchant(billFetchByBillIdRequest.getMid());
LOGGER.debug("Merchant validated successfully for MID={}", billFetchByBillIdRequest.getMid());
LOGGER.info("Calling external BBPS API for FetchBillById, URL={}", fullUrl);
Map<String, String> responseMap = httpService.getRequest(fullUrl, headers);
String responseData = responseMap.get("data");
LOGGER.info("Response received from BBPS for billId={} : {}", billId, responseData);
BharatConnectMaster headersData = beneficiaryDetailsRepository.findByOrgId("ORG001");
HttpHeaders headers = new HttpHeaders();
headers.set("x-digiledge-key", headersData.getXDigiledgeKey());
headers.set("agentId", headersData.getAgentId());
headers.set("tenantId", headersData.getTenantId());
headers.setContentType(MediaType.APPLICATION_JSON);
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> dataMap = objectMapper.readValue(responseData,
new TypeReference<Map<String, Object>>() {
});
// create outbound log
OutboundTraceLog outboundLog = helper.createOutboundLog(txnId, reqId, apiName, fullUrl, "GET", null);
LOGGER.info("Calling external BBPS API for FetchBillById, URL={}", fullUrl);
Map<String, String> responseMap = httpService.getRequest(fullUrl, headers);
String responseData = responseMap.get("data");
LOGGER.info("Response received from BBPS for billId={} : {}", billId, responseData);
if (!dataMap.containsKey("genericResponse")) {
LOGGER.warn("Invalid response structure received for billId={} | Response={}", billId, responseData);
throw new CustomException(String.valueOf(dataMap.get("message")), // message
String.valueOf(dataMap.get("status")), // status
Integer.parseInt(String.valueOf(dataMap.get("statusCode"))), // statusCode
String.valueOf(dataMap.get("remarks")));
}
// update outbound log with response
helper.updateOutboundLogResponse(outboundLog, responseData);
BillDataResponse responseWrapper = objectMapper.convertValue(dataMap, BillDataResponse.class);
GeneralResp generalResp = responseWrapper.getGenericResponse();
ResponseModel responseModel = new ResponseModel(generalResp.getMessage(), generalResp.getStatus(),
Integer.parseInt(generalResp.getStatusCode()), responseWrapper);
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> dataMap = objectMapper.readValue(responseData,
new TypeReference<Map<String, Object>>() {
});
helper.saveOrUpdateBillData(responseWrapper, billFetchByBillIdRequest, txnId);
LOGGER.info("Bill data saved successfully for billId={} | Status={}", billId, generalResp.getStatus());
if (!dataMap.containsKey("genericResponse")) {
helper.updateInboundLogFailure(inboundLog, responseData, "INVALID_RESPONSE");
LOGGER.warn("Invalid response structure received for billId={} | Response={}", billId, responseData);
throw new CustomException(String.valueOf(dataMap.get("message")), // message
String.valueOf(dataMap.get("status")), // status
Integer.parseInt(String.valueOf(dataMap.get("statusCode"))), // statusCode
String.valueOf(dataMap.get("remarks")));
}
return responseModel;
BillDataResponse responseWrapper = objectMapper.convertValue(dataMap, BillDataResponse.class);
GeneralResp generalResp = responseWrapper.getGenericResponse();
ResponseModel responseModel = new ResponseModel(generalResp.getMessage(), generalResp.getStatus(),
Integer.parseInt(generalResp.getStatusCode()), responseWrapper);
} catch (JsonProcessingException e) {
LOGGER.error("Error parsing responseData JSON for billId={} : {}", billId, e.getMessage(), e);
throw new CustomException("Invalid JSON received from API");
}
// update inbound log success and persist bill data
helper.updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus());
helper.saveOrUpdateBillData(responseWrapper, billFetchByBillIdRequest, txnId);
LOGGER.info("Bill data saved successfully for billId={} | Status={}", billId, generalResp.getStatus());
return responseModel;
} catch (JsonProcessingException e) {
LOGGER.error("Error parsing responseData JSON for billId={} : {}", billId, e.getMessage(), e);
helper.updateInboundLogFailure(inboundLog, e.getMessage(), "JSON_ERROR");
throw new CustomException("Invalid JSON received from API");
}
}
@Override
public ResponseModel initiateBillValidate(FetchBillValidatestRequest fetchBillValidateRequest) {
public ResponseModel initiateBillValidate(FetchBillValidatestRequest fetchBillValidateRequest) {
LOGGER.info("Initiating bill Validate for request ID: {} and MID:{} and billerId:{}", fetchBillValidateRequest.getReqId(),
fetchBillValidateRequest.getMid(),fetchBillValidateRequest.getBillerId());
LOGGER.info("Initiating bill Validate for request ID: {} and MID", fetchBillValidateRequest.getReqId(),
fetchBillValidateRequest.getMid());
String apiName = "InitiateBillValidate";
String txnId = helper.generateTxnId(15);
String reqId = fetchBillValidateRequest.getReqId();
@@ -436,9 +452,74 @@ public class AgentServiceImpl implements AgentService {
}
}
// ================================== Bill fetch and Bill Validate by Client Req
// Id==================================//
@Override
public ResponseModel initiateBillValidateByBillId(BillFetchByBillIdRequest billRequest) {
String apiName = "FetchBillById";
String txnId = helper.generateTxnId(15);
String reqId = billRequest.getReqId();
String billId = billRequest.getBillId();
String fullUrl = agentDtaUrl + BBPSConstant.BILL_VALIDATE_ID_URL + billRequest.getBillId();
LOGGER.info("Initiating {} API for billId={} and reqId={}", apiName, billId, reqId);
// create inbound log (GET -> no request body)
InboundTraceLog inboundLog = helper.createInboundLog(reqId, txnId, apiName, billRequest.getMid(), "GET", null);
try {
helper.validateMerchant(billRequest.getMid());
BharatConnectMaster headersData = beneficiaryDetailsRepository.findByOrgId("ORG001");
HttpHeaders headers = new HttpHeaders();
headers.set("x-digiledge-key", headersData.getXDigiledgeKey());
headers.set("agentId", headersData.getAgentId());
headers.set("tenantId", headersData.getTenantId());
headers.setContentType(MediaType.APPLICATION_JSON);
// create outbound log
OutboundTraceLog outboundLog = helper.createOutboundLog(txnId, reqId, apiName, fullUrl, "GET", null);
LOGGER.info("Calling external BBPS API for ValidateByBillId, URL={}", fullUrl);
Map<String, String> responseMap = httpService.getRequest(fullUrl, headers);
String responseData = responseMap.get("data");
LOGGER.info("Response received from BBPS for billId={} : {}", billId, responseData);
// update outbound log with response
helper.updateOutboundLogResponse(outboundLog, responseData);
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> dataMap = objectMapper.readValue(responseData, new com.fasterxml.jackson.core.type.TypeReference<Map<String, Object>>(){});
if (!dataMap.containsKey("genericResponse")) {
helper.updateInboundLogFailure(inboundLog, responseData, "INVALID_RESPONSE");
LOGGER.warn("Invalid response structure received for billId={} | Response={}", billId, responseData);
throw new CustomException(String.valueOf(dataMap.get("message")),
String.valueOf(dataMap.get("status")),
Integer.parseInt(String.valueOf(dataMap.get("statusCode"))),
String.valueOf(dataMap.get("remarks")));
}
FetchBillValidateResponse responseWrapper = objectMapper.convertValue(dataMap, FetchBillValidateResponse.class);
GeneralResp generalResp = responseWrapper.getGenericResponse();
// update inbound log and save validation data
helper.updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus());
helper.saveBillValidation(responseWrapper, billRequest);
LOGGER.info("Bill validation saved successfully for billId: {}", billId);
return new ResponseModel(generalResp.getMessage(), generalResp.getStatus(), Integer.parseInt(generalResp.getStatusCode()), responseWrapper);
} catch (com.fasterxml.jackson.core.JsonProcessingException e) {
LOGGER.error("Error parsing ValidateByBillId JSON: {}", e.getMessage(), e);
helper.updateInboundLogFailure(inboundLog, e.getMessage(), "JSON_ERROR");
throw new CustomException("Invalid JSON received from API");
}
}
//================================== Bill fetch and Bill Validate by Client Req Id==================================//
@Override
public ResponseModel fetchBillValidateByClientReqId(BillValidateByClientIdRequest billValidateByClientIdRequest) {
@@ -568,6 +649,7 @@ public class AgentServiceImpl implements AgentService {
}
}
/*
* @Override public ResponseModel
* initiateBillValidate(FetchBillValidatestRequest fetchBillValidateRequest) {
@@ -755,9 +837,5 @@ public class AgentServiceImpl implements AgentService {
* }
*/
@Override
public ResponseModel initiateBillValidateByBillId(BillFetchByBillIdRequest billRequest) {
// TODO Auto-generated method stub
return null;
}
}
@@ -196,7 +196,8 @@ public class MasterDataServiceImpl implements MasterDataService {
mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
BillerDetails entity = mapper.map(responseWrapper.getBillerDAO(), BillerDetails.class);
EntityRelationshipUtil.linkBillerRelationships(entity);// linking nesting entity foreign key
// helper.saveOrUpdateBillerData(entity);
helper.saveOrUpdateBillerData(entity);
ResponseModel responseModel = new ResponseModel(generalResp.getMessage(), generalResp.getStatus(),
Integer.parseInt(generalResp.getStatusCode()), responseWrapper);
helper.updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus());
@@ -37,6 +37,10 @@ public class EntityRelationshipUtil {
entity.getBillerAdditionalInfos().forEach(a -> a.setBiller(entity));
}
if(entity.getBillerAdditionalInfoPayments() != null) {
entity.getBillerAdditionalInfoPayments().forEach(a -> a.setBiller(entity));
}
if (entity.getInterchangeFees() != null) {
for (InterchangeFee fee : entity.getInterchangeFees()) {
@@ -26,6 +26,7 @@ import com.billpaymentservice.bbps.dto.sentRequest.BillPaymentForwardRequest;
import com.billpaymentservice.bbps.dto.sentRequest.FetchBillForwardRequest;
import com.billpaymentservice.bbps.dto.sentRequest.FetchBillValidatestForwardRequest;
import com.billpaymentservice.bbps.entites.AdditionalInfoBill;
import com.billpaymentservice.bbps.entites.AdditionalInfoBillValidate;
import com.billpaymentservice.bbps.entites.BBPSMastersData;
import com.billpaymentservice.bbps.entites.BillMaster;
import com.billpaymentservice.bbps.entites.BillValidation;
@@ -218,32 +219,7 @@ public class Helper {
Optional<BillerDetails> existingOpt = billerDataRespository.findByBillerId(newEntity.getBillerId());
if (existingOpt.isPresent()) {
BillerDetails existing = existingOpt.get();
// Update base biller fields
existing.setBillerName(newEntity.getBillerName());
existing.setBillerAliasName(newEntity.getBillerAliasName());
existing.setBillerDescription(newEntity.getBillerDescription());
existing.setStatus(newEntity.getStatus());
existing.setBillerCoverage(newEntity.getBillerCoverage());
// ... (update other simple fields as needed)
// ✅ Clear and replace nested lists to avoid duplicate inserts
existing.getBillerPaymentModes().clear();
if (newEntity.getBillerPaymentModes() != null) {
for (PaymentMode mode : newEntity.getBillerPaymentModes()) {
mode.setBiller(existing);
existing.getBillerPaymentModes().add(mode);
}
}
existing.getBillerPaymentChannels().clear();
if (newEntity.getBillerPaymentChannels() != null) {
for (PaymentChannel channel : newEntity.getBillerPaymentChannels()) {
channel.setBiller(existing);
existing.getBillerPaymentChannels().add(channel);
}
}
billerDataRespository.save(existing);
//logic to be written
}
else {
// brand new biller
@@ -348,7 +324,18 @@ billMasterRepository.save(billMaster);
.collect(Collectors.toList());
billEntity.setCustomerParams(customerParams);
}
if (responseWrapper.getAdditionalInfo() != null) {
List<AdditionalInfoBillValidate> additionalInfos = responseWrapper.getAdditionalInfo()
.stream()
.map(info -> {
AdditionalInfoBillValidate ai = modelMapper.map(info, AdditionalInfoBillValidate.class);
ai.setBill(billEntity); // maintain relation
return ai;
})
.collect(Collectors.toList());
billEntity.setAdditionalInfo(additionalInfos);
}
// ✅ Save everything (cascade handles child)
billValidationRepository.save(billEntity);
@@ -20,9 +20,9 @@ swagger.server.description=Local Development Server
# DataSource
spring.datasource.url=jdbc:postgresql://localhost:5432/BBPS
spring.datasource.username=postgres
spring.datasource.password=UAT@DB_2025
#spring.datasource.password=UAT@DB_2025
#spring.datasource.password=himanshu@123
spring.datasource.password=himanshu@123
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.type=com.zaxxer.hikari.HikariDataSource