biller-cli 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. biller_cli/__init__.py +0 -0
  2. biller_cli/ai/__init__.py +397 -0
  3. biller_cli/ai/ingest.py +394 -0
  4. biller_cli/commands/down.py +96 -0
  5. biller_cli/commands/downgrade.py +142 -0
  6. biller_cli/commands/init.py +210 -0
  7. biller_cli/commands/up.py +138 -0
  8. biller_cli/commands/upgrade.py +271 -0
  9. biller_cli/main.py +34 -0
  10. biller_cli/templates/biller-user-layer/pom.xml +100 -0
  11. biller_cli/templates/biller-user-layer/src/main/java/bharat/connect/biller/ApplicationContext.java +13 -0
  12. biller_cli/templates/biller-user-layer/src/main/java/bharat/connect/biller/config/DatabaseConfig.java +35 -0
  13. biller_cli/templates/biller-user-layer/src/main/java/bharat/connect/biller/config/WebCorsConfig.java +21 -0
  14. biller_cli/templates/biller-user-layer/src/main/java/bharat/connect/biller/controller/BbpsRequestController.java +98 -0
  15. biller_cli/templates/biller-user-layer/src/main/java/bharat/connect/biller/dao/impl/BillFetchDaoImpl.java +135 -0
  16. biller_cli/templates/biller-user-layer/src/main/java/bharat/connect/biller/dao/impl/BillPaymentDaoImpl.java +100 -0
  17. biller_cli/templates/biller-user-layer/src/main/java/bharat/connect/biller/provider/BillingProviderConfig.java +34 -0
  18. biller_cli/templates/biller-user-layer/src/main/java/bharat/connect/biller/provider/BillingProviderProperties.java +92 -0
  19. biller_cli/templates/biller-user-layer/src/main/java/bharat/connect/biller/provider/impl/CsvBillingProvider.java +257 -0
  20. biller_cli/templates/biller-user-layer/src/main/java/bharat/connect/biller/provider/impl/ExcelBillingProvider.java +261 -0
  21. biller_cli/templates/biller-user-layer/src/main/java/bharat/connect/biller/provider/impl/PostgresBillingProvider.java +210 -0
  22. biller_cli/templates/biller-user-layer/src/main/java/bharat/connect/biller/service/impl/BillFetchServiceImpl.java +131 -0
  23. biller_cli/templates/biller-user-layer/src/main/java/bharat/connect/biller/service/impl/BillPaymentServiceImpl.java +175 -0
  24. biller_cli/templates/biller-user-layer/src/main/java/bharat/connect/biller/service/impl/HeartbeatServiceImpl.java +136 -0
  25. biller_cli/templates/biller-user-layer/src/main/resources/application.properties +88 -0
  26. biller_cli/templates/pom.xml +33 -0
  27. biller_cli/utils/preflight.py +151 -0
  28. biller_cli/utils/secrets.py +37 -0
  29. biller_cli/utils/version_pin.py +67 -0
  30. biller_cli-0.1.0.dist-info/METADATA +17 -0
  31. biller_cli-0.1.0.dist-info/RECORD +33 -0
  32. biller_cli-0.1.0.dist-info/WHEEL +4 -0
  33. biller_cli-0.1.0.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,257 @@
1
+ package bharat.connect.biller.provider.impl;
2
+
3
+ import bharat.connect.biller.model.BillDetails;
4
+ import bharat.connect.biller.provider.BillingProvider;
5
+ import bharat.connect.biller.provider.BillingProviderProperties;
6
+ import bharat.connect.biller.provider.CustomerParamCriterion;
7
+ import bharat.connect.biller.provider.PaymentUpdateRequest;
8
+ import bharat.connect.biller.provider.ProviderSupport;
9
+
10
+ import java.io.IOException;
11
+ import java.math.BigDecimal;
12
+ import java.nio.charset.StandardCharsets;
13
+ import java.nio.file.Files;
14
+ import java.nio.file.Path;
15
+ import java.nio.file.Paths;
16
+ import java.nio.file.StandardCopyOption;
17
+ import java.nio.file.StandardOpenOption;
18
+ import java.time.LocalDate;
19
+ import java.time.format.DateTimeFormatter;
20
+ import java.util.ArrayList;
21
+ import java.util.HashMap;
22
+ import java.util.List;
23
+ import java.util.Map;
24
+ import java.util.Optional;
25
+ import java.util.stream.Collectors;
26
+
27
+ public class CsvBillingProvider implements BillingProvider {
28
+ private static final String UNPAID = "UNPAID";
29
+ private static final String PAID = "PAID";
30
+
31
+ private final BillingProviderProperties properties;
32
+ private final DateTimeFormatter dateFormatter;
33
+
34
+ public CsvBillingProvider(BillingProviderProperties properties) {
35
+ this.properties = properties;
36
+ this.dateFormatter = DateTimeFormatter.ofPattern(properties.getDateFormat());
37
+ }
38
+
39
+ @Override
40
+ public BillDetails findLatestUnpaidBill(List<CustomerParamCriterion> criteria) {
41
+ List<CsvRow> rows = readRows();
42
+ return rows.stream()
43
+ .map(CsvRow::toBillDetails)
44
+ .filter(b -> UNPAID.equalsIgnoreCase(b.getBillStatus()))
45
+ .filter(b -> ProviderSupport.matches(criteria, b))
46
+ .sorted(ProviderSupport.latestUnpaidOrder())
47
+ .findFirst()
48
+ .orElse(null);
49
+ }
50
+
51
+ @Override
52
+ public boolean markBillPaidAndRecordTransaction(List<CustomerParamCriterion> criteria, PaymentUpdateRequest paymentUpdateRequest) {
53
+ List<CsvRow> rows = readRows();
54
+ Optional<CsvRow> latest = rows.stream()
55
+ .filter(r -> UNPAID.equalsIgnoreCase(r.getStatus()))
56
+ .filter(r -> ProviderSupport.matches(criteria, r.toBillDetails()))
57
+ .sorted((a, b) -> ProviderSupport.latestUnpaidOrder().compare(a.toBillDetails(), b.toBillDetails()))
58
+ .findFirst();
59
+ if (latest.isEmpty()) {
60
+ return false;
61
+ }
62
+ latest.get().setStatus(PAID);
63
+ writeRowsAtomically(rows);
64
+ appendPaymentLog(paymentUpdateRequest);
65
+ return true;
66
+ }
67
+
68
+ private List<CsvRow> readRows() {
69
+ Path path = Paths.get(properties.getCsv().getPath());
70
+ if (!Files.exists(path)) {
71
+ return List.of();
72
+ }
73
+ try {
74
+ List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
75
+ if (lines.isEmpty()) {
76
+ return List.of();
77
+ }
78
+ String delimiter = properties.getCsv().getDelimiter();
79
+ String[] headers = split(lines.get(0), delimiter);
80
+ Map<String, Integer> indexByHeader = new HashMap<>();
81
+ for (int i = 0; i < headers.length; i++) {
82
+ indexByHeader.put(headers[i].trim(), i);
83
+ }
84
+ List<CsvRow> rows = new ArrayList<>();
85
+ for (int i = 1; i < lines.size(); i++) {
86
+ if (lines.get(i).isBlank()) {
87
+ continue;
88
+ }
89
+ String[] values = split(lines.get(i), delimiter);
90
+ rows.add(CsvRow.from(values, indexByHeader, properties.getCsv().getColumns(), dateFormatter));
91
+ }
92
+ return rows;
93
+ } catch (IOException e) {
94
+ throw new IllegalStateException("Failed to read csv provider file", e);
95
+ }
96
+ }
97
+
98
+ private void writeRowsAtomically(List<CsvRow> rows) {
99
+ Path source = Paths.get(properties.getCsv().getPath());
100
+ Path temp = source.resolveSibling(source.getFileName() + ".tmp");
101
+ BillingProviderProperties.Columns columns = properties.getCsv().getColumns();
102
+ String delimiter = properties.getCsv().getDelimiter();
103
+
104
+ String header = String.join(delimiter,
105
+ columns.getBillId(),
106
+ columns.getCustomerParamName(),
107
+ columns.getCustomerParamType(),
108
+ columns.getCustomerParamValue(),
109
+ columns.getBillAmount(),
110
+ columns.getBillDate(),
111
+ columns.getDueDate(),
112
+ columns.getBillNumber(),
113
+ columns.getBillPeriod(),
114
+ columns.getBillStatus()
115
+ );
116
+ List<String> lines = new ArrayList<>();
117
+ lines.add(header);
118
+ lines.addAll(rows.stream().map(r -> r.toCsvLine(delimiter, dateFormatter)).collect(Collectors.toList()));
119
+ try {
120
+ Files.write(temp, lines, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE);
121
+ Files.move(temp, source, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE);
122
+ } catch (IOException e) {
123
+ throw new IllegalStateException("Failed to write csv provider file", e);
124
+ }
125
+ }
126
+
127
+ private void appendPaymentLog(PaymentUpdateRequest paymentUpdateRequest) {
128
+ String paymentLogPath = properties.getCsv().getPaymentLogPath();
129
+ if (paymentLogPath == null || paymentLogPath.isBlank()) {
130
+ return;
131
+ }
132
+ Path path = Paths.get(paymentLogPath);
133
+ try {
134
+ if (!Files.exists(path)) {
135
+ Files.write(path, List.of("bill_id,bbps_txn_ref,amount_paid,payment_mode"), StandardCharsets.UTF_8,
136
+ StandardOpenOption.CREATE, StandardOpenOption.WRITE);
137
+ }
138
+ String line = String.format("%s,%s,%s,%s",
139
+ paymentUpdateRequest.getBillId(),
140
+ paymentUpdateRequest.getBbpsTxnRef(),
141
+ paymentUpdateRequest.getAmountPaid(),
142
+ paymentUpdateRequest.getPaymentMode() == null ? "" : paymentUpdateRequest.getPaymentMode());
143
+ Files.write(path, List.of(line), StandardCharsets.UTF_8, StandardOpenOption.APPEND);
144
+ } catch (IOException e) {
145
+ throw new IllegalStateException("Failed to append csv payment log", e);
146
+ }
147
+ }
148
+
149
+ private String[] split(String line, String delimiter) {
150
+ return line.split(java.util.regex.Pattern.quote(delimiter), -1);
151
+ }
152
+
153
+ private static class CsvRow {
154
+ private Long billId;
155
+ private String customerParamName;
156
+ private String customerParamType;
157
+ private String customerParamValue;
158
+ private BigDecimal billAmount;
159
+ private LocalDate billDate;
160
+ private LocalDate dueDate;
161
+ private String billNumber;
162
+ private String billPeriod;
163
+ private String status;
164
+
165
+ static CsvRow from(String[] values,
166
+ Map<String, Integer> indexByHeader,
167
+ BillingProviderProperties.Columns columns,
168
+ DateTimeFormatter dateFormatter) {
169
+ CsvRow row = new CsvRow();
170
+ row.billId = parseLong(read(values, indexByHeader, columns.getBillId()));
171
+ row.customerParamName = read(values, indexByHeader, columns.getCustomerParamName());
172
+ row.customerParamType = read(values, indexByHeader, columns.getCustomerParamType());
173
+ row.customerParamValue = read(values, indexByHeader, columns.getCustomerParamValue());
174
+ row.billAmount = parseBigDecimal(read(values, indexByHeader, columns.getBillAmount()));
175
+ row.billDate = parseDate(read(values, indexByHeader, columns.getBillDate()), dateFormatter);
176
+ row.dueDate = parseDate(read(values, indexByHeader, columns.getDueDate()), dateFormatter);
177
+ row.billNumber = read(values, indexByHeader, columns.getBillNumber());
178
+ row.billPeriod = read(values, indexByHeader, columns.getBillPeriod());
179
+ row.status = read(values, indexByHeader, columns.getBillStatus());
180
+ return row;
181
+ }
182
+
183
+ BillDetails toBillDetails() {
184
+ BillDetails details = new BillDetails();
185
+ details.setBillId(billId);
186
+ details.setCustomerParamName(customerParamName);
187
+ details.setCustomerParamType(customerParamType);
188
+ details.setCustomerParamValue(customerParamValue);
189
+ details.setBillAmount(billAmount);
190
+ details.setBillDate(billDate);
191
+ details.setDueDate(dueDate);
192
+ details.setBillNumber(billNumber);
193
+ details.setBillPeriod(billPeriod);
194
+ details.setBillStatus(status);
195
+ return details;
196
+ }
197
+
198
+ String toCsvLine(String delimiter, DateTimeFormatter dateFormatter) {
199
+ return String.join(delimiter,
200
+ nullable(billId),
201
+ nullable(customerParamName),
202
+ nullable(customerParamType),
203
+ nullable(customerParamValue),
204
+ nullable(billAmount),
205
+ formatDate(billDate, dateFormatter),
206
+ formatDate(dueDate, dateFormatter),
207
+ nullable(billNumber),
208
+ nullable(billPeriod),
209
+ nullable(status));
210
+ }
211
+
212
+ String getStatus() {
213
+ return status;
214
+ }
215
+
216
+ void setStatus(String status) {
217
+ this.status = status;
218
+ }
219
+
220
+ private static String read(String[] values, Map<String, Integer> indexByHeader, String key) {
221
+ Integer idx = indexByHeader.get(key);
222
+ if (idx == null || idx < 0 || idx >= values.length) {
223
+ return null;
224
+ }
225
+ return values[idx];
226
+ }
227
+
228
+ private static Long parseLong(String value) {
229
+ if (value == null || value.isBlank()) {
230
+ return null;
231
+ }
232
+ return Long.parseLong(value.trim());
233
+ }
234
+
235
+ private static BigDecimal parseBigDecimal(String value) {
236
+ if (value == null || value.isBlank()) {
237
+ return null;
238
+ }
239
+ return new BigDecimal(value.trim());
240
+ }
241
+
242
+ private static LocalDate parseDate(String value, DateTimeFormatter formatter) {
243
+ if (value == null || value.isBlank()) {
244
+ return null;
245
+ }
246
+ return LocalDate.parse(value.trim(), formatter);
247
+ }
248
+
249
+ private static String nullable(Object value) {
250
+ return value == null ? "" : String.valueOf(value);
251
+ }
252
+
253
+ private static String formatDate(LocalDate date, DateTimeFormatter formatter) {
254
+ return date == null ? "" : formatter.format(date);
255
+ }
256
+ }
257
+ }
@@ -0,0 +1,261 @@
1
+ package bharat.connect.biller.provider.impl;
2
+
3
+ import bharat.connect.biller.model.BillDetails;
4
+ import bharat.connect.biller.provider.BillingProvider;
5
+ import bharat.connect.biller.provider.BillingProviderProperties;
6
+ import bharat.connect.biller.provider.CustomerParamCriterion;
7
+ import bharat.connect.biller.provider.PaymentUpdateRequest;
8
+ import bharat.connect.biller.provider.ProviderSupport;
9
+ import org.apache.poi.ss.usermodel.Cell;
10
+ import org.apache.poi.ss.usermodel.DataFormatter;
11
+ import org.apache.poi.ss.usermodel.Row;
12
+ import org.apache.poi.ss.usermodel.Sheet;
13
+ import org.apache.poi.ss.usermodel.Workbook;
14
+ import org.apache.poi.xssf.usermodel.XSSFWorkbook;
15
+
16
+ import java.io.IOException;
17
+ import java.io.InputStream;
18
+ import java.io.OutputStream;
19
+ import java.math.BigDecimal;
20
+ import java.nio.charset.StandardCharsets;
21
+ import java.nio.file.Files;
22
+ import java.nio.file.Path;
23
+ import java.nio.file.Paths;
24
+ import java.nio.file.StandardOpenOption;
25
+ import java.time.LocalDate;
26
+ import java.time.format.DateTimeFormatter;
27
+ import java.util.ArrayList;
28
+ import java.util.HashMap;
29
+ import java.util.List;
30
+ import java.util.Map;
31
+ import java.util.Optional;
32
+
33
+ public class ExcelBillingProvider implements BillingProvider {
34
+ private static final String UNPAID = "UNPAID";
35
+ private static final String PAID = "PAID";
36
+
37
+ private final BillingProviderProperties properties;
38
+ private final DateTimeFormatter dateFormatter;
39
+ private final DataFormatter dataFormatter = new DataFormatter();
40
+
41
+ public ExcelBillingProvider(BillingProviderProperties properties) {
42
+ this.properties = properties;
43
+ this.dateFormatter = DateTimeFormatter.ofPattern(properties.getDateFormat());
44
+ }
45
+
46
+ @Override
47
+ public BillDetails findLatestUnpaidBill(List<CustomerParamCriterion> criteria) {
48
+ List<ExcelRow> rows = readRows();
49
+ return rows.stream()
50
+ .map(ExcelRow::toBillDetails)
51
+ .filter(b -> UNPAID.equalsIgnoreCase(b.getBillStatus()))
52
+ .filter(b -> ProviderSupport.matches(criteria, b))
53
+ .sorted(ProviderSupport.latestUnpaidOrder())
54
+ .findFirst()
55
+ .orElse(null);
56
+ }
57
+
58
+ @Override
59
+ public boolean markBillPaidAndRecordTransaction(List<CustomerParamCriterion> criteria, PaymentUpdateRequest paymentUpdateRequest) {
60
+ List<ExcelRow> rows = readRows();
61
+ Optional<ExcelRow> latest = rows.stream()
62
+ .filter(r -> UNPAID.equalsIgnoreCase(r.status))
63
+ .filter(r -> ProviderSupport.matches(criteria, r.toBillDetails()))
64
+ .sorted((a, b) -> ProviderSupport.latestUnpaidOrder().compare(a.toBillDetails(), b.toBillDetails()))
65
+ .findFirst();
66
+ if (latest.isEmpty()) {
67
+ return false;
68
+ }
69
+ latest.get().status = PAID;
70
+ writeRows(rows);
71
+ appendPaymentLog(paymentUpdateRequest);
72
+ return true;
73
+ }
74
+
75
+ private List<ExcelRow> readRows() {
76
+ Path path = Paths.get(properties.getExcel().getPath());
77
+ if (!Files.exists(path)) {
78
+ return List.of();
79
+ }
80
+ try (InputStream in = Files.newInputStream(path, StandardOpenOption.READ);
81
+ Workbook workbook = new XSSFWorkbook(in)) {
82
+ Sheet sheet = workbook.getSheet(properties.getExcel().getSheetName());
83
+ if (sheet == null || sheet.getPhysicalNumberOfRows() == 0) {
84
+ return List.of();
85
+ }
86
+ Row header = sheet.getRow(0);
87
+ Map<String, Integer> indexByHeader = new HashMap<>();
88
+ for (Cell cell : header) {
89
+ indexByHeader.put(cell.getStringCellValue(), cell.getColumnIndex());
90
+ }
91
+ List<ExcelRow> rows = new ArrayList<>();
92
+ for (int i = 1; i <= sheet.getLastRowNum(); i++) {
93
+ Row row = sheet.getRow(i);
94
+ if (row == null) {
95
+ continue;
96
+ }
97
+ rows.add(ExcelRow.from(row, indexByHeader, properties.getExcel().getColumns(), dateFormatter, dataFormatter));
98
+ }
99
+ return rows;
100
+ } catch (IOException e) {
101
+ throw new IllegalStateException("Failed to read excel provider file", e);
102
+ }
103
+ }
104
+
105
+ private void writeRows(List<ExcelRow> rows) {
106
+ Path path = Paths.get(properties.getExcel().getPath());
107
+ try (Workbook workbook = new XSSFWorkbook()) {
108
+ Sheet sheet = workbook.createSheet(properties.getExcel().getSheetName());
109
+ BillingProviderProperties.Columns columns = properties.getExcel().getColumns();
110
+ Row header = sheet.createRow(0);
111
+ String[] headerValues = {
112
+ columns.getBillId(),
113
+ columns.getCustomerParamName(),
114
+ columns.getCustomerParamType(),
115
+ columns.getCustomerParamValue(),
116
+ columns.getBillAmount(),
117
+ columns.getBillDate(),
118
+ columns.getDueDate(),
119
+ columns.getBillNumber(),
120
+ columns.getBillPeriod(),
121
+ columns.getBillStatus()
122
+ };
123
+ for (int i = 0; i < headerValues.length; i++) {
124
+ header.createCell(i).setCellValue(headerValues[i]);
125
+ }
126
+
127
+ int rowIndex = 1;
128
+ for (ExcelRow row : rows) {
129
+ Row xlsRow = sheet.createRow(rowIndex++);
130
+ row.writeTo(xlsRow, dateFormatter);
131
+ }
132
+ try (OutputStream out = Files.newOutputStream(path, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE)) {
133
+ workbook.write(out);
134
+ }
135
+ } catch (IOException e) {
136
+ throw new IllegalStateException("Failed to write excel provider file", e);
137
+ }
138
+ }
139
+
140
+ private void appendPaymentLog(PaymentUpdateRequest paymentUpdateRequest) {
141
+ String paymentLogPath = properties.getExcel().getPaymentLogPath();
142
+ if (paymentLogPath == null || paymentLogPath.isBlank()) {
143
+ return;
144
+ }
145
+ Path path = Paths.get(paymentLogPath);
146
+ try {
147
+ if (!Files.exists(path)) {
148
+ Files.write(path, List.of("bill_id,bbps_txn_ref,amount_paid,payment_mode"), StandardCharsets.UTF_8,
149
+ StandardOpenOption.CREATE, StandardOpenOption.WRITE);
150
+ }
151
+ String line = String.format("%s,%s,%s,%s",
152
+ paymentUpdateRequest.getBillId(),
153
+ paymentUpdateRequest.getBbpsTxnRef(),
154
+ paymentUpdateRequest.getAmountPaid(),
155
+ paymentUpdateRequest.getPaymentMode() == null ? "" : paymentUpdateRequest.getPaymentMode());
156
+ Files.write(path, List.of(line), StandardCharsets.UTF_8, StandardOpenOption.APPEND);
157
+ } catch (IOException e) {
158
+ throw new IllegalStateException("Failed to append excel payment log", e);
159
+ }
160
+ }
161
+
162
+ private static class ExcelRow {
163
+ private Long billId;
164
+ private String customerParamName;
165
+ private String customerParamType;
166
+ private String customerParamValue;
167
+ private BigDecimal billAmount;
168
+ private LocalDate billDate;
169
+ private LocalDate dueDate;
170
+ private String billNumber;
171
+ private String billPeriod;
172
+ private String status;
173
+
174
+ static ExcelRow from(Row row,
175
+ Map<String, Integer> indexByHeader,
176
+ BillingProviderProperties.Columns columns,
177
+ DateTimeFormatter dateFormatter,
178
+ DataFormatter dataFormatter) {
179
+ ExcelRow data = new ExcelRow();
180
+ data.billId = parseLong(getCellString(row, indexByHeader.get(columns.getBillId()), dataFormatter));
181
+ data.customerParamName = getCellString(row, indexByHeader.get(columns.getCustomerParamName()), dataFormatter);
182
+ data.customerParamType = getCellString(row, indexByHeader.get(columns.getCustomerParamType()), dataFormatter);
183
+ data.customerParamValue = getCellString(row, indexByHeader.get(columns.getCustomerParamValue()), dataFormatter);
184
+ data.billAmount = parseBigDecimal(getCellString(row, indexByHeader.get(columns.getBillAmount()), dataFormatter));
185
+ data.billDate = parseDate(getCellString(row, indexByHeader.get(columns.getBillDate()), dataFormatter), dateFormatter);
186
+ data.dueDate = parseDate(getCellString(row, indexByHeader.get(columns.getDueDate()), dataFormatter), dateFormatter);
187
+ data.billNumber = getCellString(row, indexByHeader.get(columns.getBillNumber()), dataFormatter);
188
+ data.billPeriod = getCellString(row, indexByHeader.get(columns.getBillPeriod()), dataFormatter);
189
+ data.status = getCellString(row, indexByHeader.get(columns.getBillStatus()), dataFormatter);
190
+ return data;
191
+ }
192
+
193
+ BillDetails toBillDetails() {
194
+ BillDetails details = new BillDetails();
195
+ details.setBillId(billId);
196
+ details.setCustomerParamName(customerParamName);
197
+ details.setCustomerParamType(customerParamType);
198
+ details.setCustomerParamValue(customerParamValue);
199
+ details.setBillAmount(billAmount);
200
+ details.setBillDate(billDate);
201
+ details.setDueDate(dueDate);
202
+ details.setBillNumber(billNumber);
203
+ details.setBillPeriod(billPeriod);
204
+ details.setBillStatus(status);
205
+ return details;
206
+ }
207
+
208
+ void writeTo(Row row, DateTimeFormatter formatter) {
209
+ row.createCell(0).setCellValue(nullable(billId));
210
+ row.createCell(1).setCellValue(nullable(customerParamName));
211
+ row.createCell(2).setCellValue(nullable(customerParamType));
212
+ row.createCell(3).setCellValue(nullable(customerParamValue));
213
+ row.createCell(4).setCellValue(nullable(billAmount));
214
+ row.createCell(5).setCellValue(formatDate(billDate, formatter));
215
+ row.createCell(6).setCellValue(formatDate(dueDate, formatter));
216
+ row.createCell(7).setCellValue(nullable(billNumber));
217
+ row.createCell(8).setCellValue(nullable(billPeriod));
218
+ row.createCell(9).setCellValue(nullable(status));
219
+ }
220
+
221
+ private static String getCellString(Row row, Integer index, DataFormatter dataFormatter) {
222
+ if (index == null) {
223
+ return null;
224
+ }
225
+ Cell cell = row.getCell(index);
226
+ if (cell == null) {
227
+ return null;
228
+ }
229
+ return dataFormatter.formatCellValue(cell);
230
+ }
231
+
232
+ private static Long parseLong(String value) {
233
+ if (value == null || value.isBlank()) {
234
+ return null;
235
+ }
236
+ return Long.parseLong(value.trim());
237
+ }
238
+
239
+ private static BigDecimal parseBigDecimal(String value) {
240
+ if (value == null || value.isBlank()) {
241
+ return null;
242
+ }
243
+ return new BigDecimal(value.trim());
244
+ }
245
+
246
+ private static LocalDate parseDate(String value, DateTimeFormatter formatter) {
247
+ if (value == null || value.isBlank()) {
248
+ return null;
249
+ }
250
+ return LocalDate.parse(value.trim(), formatter);
251
+ }
252
+
253
+ private static String nullable(Object value) {
254
+ return value == null ? "" : String.valueOf(value);
255
+ }
256
+
257
+ private static String formatDate(LocalDate date, DateTimeFormatter formatter) {
258
+ return date == null ? "" : formatter.format(date);
259
+ }
260
+ }
261
+ }