| 1 | package com.rbctcsworld.ecommerce.report; | |
| 2 | ||
| 3 | import com.rbctcsworld.ecommerce.common.Csv; | |
| 4 | import com.rbctcsworld.ecommerce.common.exception.BusinessRuleException; | |
| 5 | import com.rbctcsworld.ecommerce.common.exception.NotFoundException; | |
| 6 | import org.springframework.jdbc.core.JdbcTemplate; | |
| 7 | import org.springframework.stereotype.Service; | |
| 8 | import org.springframework.transaction.annotation.Transactional; | |
| 9 | ||
| 10 | import java.math.BigDecimal; | |
| 11 | import java.sql.Timestamp; | |
| 12 | import java.time.Clock; | |
| 13 | import java.time.LocalDate; | |
| 14 | import java.time.LocalDateTime; | |
| 15 | import java.time.YearMonth; | |
| 16 | import java.time.temporal.ChronoUnit; | |
| 17 | import java.util.ArrayList; | |
| 18 | import java.util.Arrays; | |
| 19 | import java.util.LinkedHashMap; | |
| 20 | import java.util.List; | |
| 21 | import java.util.Locale; | |
| 22 | import java.util.Map; | |
| 23 | ||
| 24 | /** | |
| 25 | * Store reports for the admin. Dates are inclusive days (from 00:00 to the end of "to"); | |
| 26 | * without dates a report covers the last 30 days up to today. At most 366 days per report. | |
| 27 | * | |
| 28 | * Money received = orders that were paid and not cancelled or returned (PAID, SHIPPED, DELIVERED, | |
| 29 | * RETURN_REQUESTED), counted on the day they were paid. | |
| 30 | */ | |
| 31 | @Service | |
| 32 | @Transactional(readOnly = true) | |
| 33 | public class ReportService { | |
| 34 | ||
| 35 | public static final List<String> NAMES = List.of("sales", "top-products", "orders-by-status", "returns", | |
| 36 | "coupons", "low-stock", "inventory", "stock-by-warehouse"); | |
| 37 | public static final int MAX_DAYS = 366; | |
| 38 | static final String PAID = "'PAID', 'SHIPPED', 'DELIVERED', 'RETURN_REQUESTED'"; | |
| 39 | static final List<String> STATUS_ORDER = List.of("PLACED", "PAID", "SHIPPED", "DELIVERED", "RETURN_REQUESTED", | |
| 40 | "RETURNED", "CANCELLED"); | |
| 41 | ||
| 42 | private final JdbcTemplate jdbc; | |
| 43 | private final Clock clock; | |
| 44 | ||
| 45 | public ReportService(JdbcTemplate jdbc, Clock clock) { | |
| 46 | this.jdbc = jdbc; | |
| 47 | this.clock = clock; | |
| 48 | } | |
| 49 | ||
| 50 | /** Options a report may use; null = its default. */ | |
| 51 | public record Options(LocalDate from, LocalDate to, String groupBy, Integer limit, Integer threshold) { | |
| 52 | public static Options none() { | |
| 53 | return new Options(null, null, null, null, null); | |
| 54 | } | |
| 55 | } | |
| 56 | ||
| 57 | public ReportTable run(String name, Options o) { | |
| 58 |
1
1. run : removed conditional - replaced equality check with false → KILLED |
String n = name == null ? "" : name.trim().toLowerCase(Locale.ROOT); |
| 59 |
1
1. run : replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::run → KILLED |
return switch (n) { |
| 60 | case "sales" -> sales(range(o), o.groupBy()); | |
| 61 | case "top-products" -> topProducts(range(o), o.limit()); | |
| 62 | case "orders-by-status" -> ordersByStatus(range(o)); | |
| 63 | case "returns" -> returns(range(o)); | |
| 64 | case "coupons" -> coupons(range(o)); | |
| 65 | case "low-stock" -> lowStock(o.threshold()); | |
| 66 | case "inventory" -> inventory(); | |
| 67 | case "stock-by-warehouse" -> stockByWarehouse(); | |
| 68 | default -> throw new NotFoundException("No such report: " + name + " (reports: " + NAMES + ")"); | |
| 69 | }; | |
| 70 | } | |
| 71 | ||
| 72 | /** The report as CSV: header, rows, and a "total" line when it has one. */ | |
| 73 | public String csv(ReportTable t) { | |
| 74 | StringBuilder s = new StringBuilder(Csv.line(t.columns())); | |
| 75 |
1
1. csv : removed call to java/util/List::forEach → KILLED |
t.rows().forEach(r -> s.append(Csv.line(r))); |
| 76 |
1
1. csv : removed conditional - replaced equality check with false → KILLED |
if (t.totals() != null) s.append(Csv.line(t.totals())); |
| 77 |
1
1. csv : replaced return value with "" for com/rbctcsworld/ecommerce/report/ReportService::csv → KILLED |
return s.toString(); |
| 78 | } | |
| 79 | ||
| 80 | // ------------------------------------------------------------------ the date range | |
| 81 | ||
| 82 | record Range(LocalDate from, LocalDate to) { | |
| 83 | LocalDateTime start() { return from.atStartOfDay(); } | |
| 84 | LocalDateTime end() { return to.plusDays(1).atStartOfDay(); } | |
| 85 | } | |
| 86 | ||
| 87 | Range range(Options o) { | |
| 88 | LocalDate today = LocalDate.now(clock); | |
| 89 |
1
1. range : removed conditional - replaced equality check with false → KILLED |
LocalDate to = o.to() == null ? today : o.to(); |
| 90 |
1
1. range : removed conditional - replaced equality check with false → KILLED |
LocalDate from = o.from() == null ? to.minusDays(29) : o.from(); |
| 91 |
1
1. range : removed conditional - replaced equality check with false → KILLED |
if (from.isAfter(to)) throw new BusinessRuleException("from must be on or before to"); |
| 92 |
3
1. range : Replaced long addition with subtraction → KILLED 2. range : changed conditional boundary → KILLED 3. range : removed conditional - replaced comparison check with false → KILLED |
if (ChronoUnit.DAYS.between(from, to) + 1 > MAX_DAYS) { |
| 93 | throw new BusinessRuleException("a report covers at most " + MAX_DAYS + " days"); | |
| 94 | } | |
| 95 |
1
1. range : replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::range → KILLED |
return new Range(from, to); |
| 96 | } | |
| 97 | ||
| 98 | // ------------------------------------------------------------------ the reports | |
| 99 | ||
| 100 | /** Money received per day or per month, every period listed (also the quiet ones). */ | |
| 101 | ReportTable sales(Range r, String groupBy) { | |
| 102 |
2
1. sales : removed conditional - replaced equality check with false → SURVIVED 2. sales : removed conditional - replaced equality check with false → KILLED |
String g = groupBy == null || groupBy.isBlank() ? "day" : groupBy.trim().toLowerCase(Locale.ROOT); |
| 103 |
2
1. sales : removed conditional - replaced equality check with false → KILLED 2. sales : removed conditional - replaced equality check with false → KILLED |
if (!g.equals("day") && !g.equals("month")) throw new BusinessRuleException("groupBy must be day or month"); |
| 104 | Map<String, BigDecimal[]> periods = new LinkedHashMap<>(); // orders, items, subtotal, discount, shipping, tax, total | |
| 105 |
1
1. sales : removed conditional - replaced equality check with false → KILLED |
if (g.equals("day")) { |
| 106 |
1
1. sales : removed conditional - replaced equality check with false → KILLED |
for (LocalDate d = r.from(); !d.isAfter(r.to()); d = d.plusDays(1)) periods.put(d.toString(), zeros(7)); |
| 107 | } else { | |
| 108 |
1
1. sales : removed conditional - replaced equality check with false → KILLED |
for (YearMonth m = YearMonth.from(r.from()); !m.isAfter(YearMonth.from(r.to())); m = m.plusMonths(1)) { |
| 109 | periods.put(m.toString(), zeros(7)); | |
| 110 | } | |
| 111 | } | |
| 112 |
1
1. sales : removed call to org/springframework/jdbc/core/JdbcTemplate::query → KILLED |
jdbc.query("select paid_at, total_items, subtotal, discount, shipping_fee, tax, total from orders " |
| 113 | + "where paid_at >= ? and paid_at < ? and status in (" + PAID + ")", rs -> { | |
| 114 | LocalDate day = rs.getTimestamp("paid_at").toLocalDateTime().toLocalDate(); | |
| 115 |
1
1. lambda$sales$1 : removed conditional - replaced equality check with false → KILLED |
BigDecimal[] p = periods.get(g.equals("day") ? day.toString() : YearMonth.from(day).toString()); |
| 116 | p[0] = p[0].add(BigDecimal.ONE); | |
| 117 | p[1] = p[1].add(BigDecimal.valueOf(rs.getInt("total_items"))); | |
| 118 | p[2] = p[2].add(rs.getBigDecimal("subtotal")); | |
| 119 | p[3] = p[3].add(rs.getBigDecimal("discount")); | |
| 120 | p[4] = p[4].add(rs.getBigDecimal("shipping_fee")); | |
| 121 | p[5] = p[5].add(rs.getBigDecimal("tax")); | |
| 122 | p[6] = p[6].add(rs.getBigDecimal("total")); | |
| 123 | }, Timestamp.valueOf(r.start()), Timestamp.valueOf(r.end())); | |
| 124 | List<List<Object>> rows = new ArrayList<>(); | |
| 125 | BigDecimal[] sum = zeros(7); | |
| 126 |
1
1. sales : removed call to java/util/Map::forEach → KILLED |
periods.forEach((period, p) -> { |
| 127 | rows.add(row(period, p)); | |
| 128 |
3
1. lambda$sales$2 : changed conditional boundary → KILLED 2. lambda$sales$2 : Changed increment from 1 to -1 → KILLED 3. lambda$sales$2 : removed conditional - replaced comparison check with false → KILLED |
for (int i = 0; i < 7; i++) sum[i] = sum[i].add(p[i]); |
| 129 | }); | |
| 130 |
1
1. sales : replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::sales → KILLED |
return new ReportTable("sales", r.from(), r.to(), |
| 131 | List.of(g, "orders", "items", "subtotal", "discount", "shipping", "tax", "total"), rows, row("total", sum)); | |
| 132 | } | |
| 133 | ||
| 134 | /** Best sellers by units, with the money they brought in (orders paid in the range). */ | |
| 135 | ReportTable topProducts(Range r, Integer limit) { | |
| 136 |
1
1. topProducts : removed conditional - replaced equality check with false → KILLED |
int n = limit == null ? 10 : limit; |
| 137 |
4
1. topProducts : changed conditional boundary → KILLED 2. topProducts : removed conditional - replaced comparison check with false → KILLED 3. topProducts : changed conditional boundary → KILLED 4. topProducts : removed conditional - replaced comparison check with false → KILLED |
if (n < 1 || n > 100) throw new BusinessRuleException("limit must be between 1 and 100"); |
| 138 | List<List<Object>> rows = jdbc.query(""" | |
| 139 | select oi.product_id, oi.sku, max(oi.product_name) as name, sum(oi.quantity) as units, | |
| 140 | count(distinct oi.order_id) as orders, sum(oi.line_total) as revenue | |
| 141 | from order_items oi join orders o on o.id = oi.order_id | |
| 142 | where o.paid_at >= ? and o.paid_at < ? and o.status in (%s) | |
| 143 | group by oi.product_id, oi.sku | |
| 144 | order by units desc, revenue desc, oi.product_id | |
| 145 | limit %d""".formatted(PAID, n), | |
| 146 |
1
1. lambda$topProducts$3 : replaced return value with Collections.emptyList for com/rbctcsworld/ecommerce/report/ReportService::lambda$topProducts$3 → KILLED |
(rs, i) -> List.<Object>of(rs.getString("sku"), rs.getString("name"), rs.getLong("units"), |
| 147 | rs.getLong("orders"), money(rs.getBigDecimal("revenue"))), | |
| 148 | Timestamp.valueOf(r.start()), Timestamp.valueOf(r.end())); | |
| 149 |
1
1. topProducts : replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::topProducts → KILLED |
return new ReportTable("top-products", r.from(), r.to(), List.of("sku", "name", "units", "orders", "revenue"), |
| 150 | rows, totals(rows, 5, 2, 4)); | |
| 151 | } | |
| 152 | ||
| 153 | /** Orders placed in the range, by where they are now (in lifecycle order). */ | |
| 154 | ReportTable ordersByStatus(Range r) { | |
| 155 | Map<String, List<Object>> byStatus = new LinkedHashMap<>(); | |
| 156 |
1
1. ordersByStatus : removed call to java/util/List::forEach → KILLED |
STATUS_ORDER.forEach(s -> byStatus.put(s, null)); |
| 157 |
1
1. ordersByStatus : removed call to org/springframework/jdbc/core/JdbcTemplate::query → KILLED |
jdbc.query("select status, count(*) as n, coalesce(sum(total), 0) as amount from orders " |
| 158 | + "where created_at >= ? and created_at < ? group by status", rs -> { | |
| 159 | byStatus.put(rs.getString("status"), List.of(rs.getString("status"), rs.getLong("n"), money(rs.getBigDecimal("amount")))); | |
| 160 | }, Timestamp.valueOf(r.start()), Timestamp.valueOf(r.end())); | |
| 161 | List<List<Object>> rows = new ArrayList<>(); | |
| 162 |
2
1. ordersByStatus : removed call to java/util/Map::forEach → KILLED 2. lambda$ordersByStatus$6 : removed conditional - replaced equality check with false → KILLED |
byStatus.forEach((s, row) -> rows.add(row == null ? List.of(s, 0L, new BigDecimal("0.00")) : row)); |
| 163 |
1
1. ordersByStatus : replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::ordersByStatus → KILLED |
return new ReportTable("orders-by-status", r.from(), r.to(), List.of("status", "orders", "amount"), rows, |
| 164 | totals(rows, 3, 1, 2)); | |
| 165 | } | |
| 166 | ||
| 167 | /** Return requests made in the range: why, what was decided, how much was refunded, how many restocked. */ | |
| 168 | ReportTable returns(Range r) { | |
| 169 | List<List<Object>> rows = jdbc.query(""" | |
| 170 | select reason, status, count(*) as n, coalesce(sum(refund_amount), 0) as refunded, | |
| 171 | sum(case when restocked then 1 else 0 end) as restocked | |
| 172 | from return_requests where created_at >= ? and created_at < ? | |
| 173 | group by reason, status order by reason, status""", | |
| 174 |
1
1. lambda$returns$7 : replaced return value with Collections.emptyList for com/rbctcsworld/ecommerce/report/ReportService::lambda$returns$7 → KILLED |
(rs, i) -> List.<Object>of(rs.getString("reason"), rs.getString("status"), rs.getLong("n"), |
| 175 | money(rs.getBigDecimal("refunded")), rs.getLong("restocked")), | |
| 176 | Timestamp.valueOf(r.start()), Timestamp.valueOf(r.end())); | |
| 177 |
1
1. returns : replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::returns → KILLED |
return new ReportTable("returns", r.from(), r.to(), List.of("reason", "status", "returns", "refunded", "restocked"), |
| 178 | rows, totals(rows, 5, 2, 3, 4)); | |
| 179 | } | |
| 180 | ||
| 181 | /** Every coupon with what it did in the range (cancelled orders do not count). */ | |
| 182 | ReportTable coupons(Range r) { | |
| 183 | List<List<Object>> rows = jdbc.query(""" | |
| 184 | select c.code, c.type, c.discount_value, c.active, count(o.id) as uses, | |
| 185 | coalesce(sum(o.discount), 0) as discount_given, coalesce(sum(o.total), 0) as order_total | |
| 186 | from coupons c left join orders o on o.coupon_code = c.code | |
| 187 | and o.created_at >= ? and o.created_at < ? and o.status <> 'CANCELLED' | |
| 188 | group by c.code, c.type, c.discount_value, c.active | |
| 189 | order by uses desc, c.code""", | |
| 190 |
1
1. lambda$coupons$8 : replaced return value with Collections.emptyList for com/rbctcsworld/ecommerce/report/ReportService::lambda$coupons$8 → KILLED |
(rs, i) -> List.<Object>of(rs.getString("code"), rs.getString("type"), money(rs.getBigDecimal("discount_value")), |
| 191 |
1
1. lambda$coupons$8 : removed conditional - replaced equality check with false → KILLED |
rs.getBoolean("active") ? "ACTIVE" : "DISABLED", rs.getLong("uses"), |
| 192 | money(rs.getBigDecimal("discount_given")), money(rs.getBigDecimal("order_total"))), | |
| 193 | Timestamp.valueOf(r.start()), Timestamp.valueOf(r.end())); | |
| 194 |
1
1. coupons : replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::coupons → KILLED |
return new ReportTable("coupons", r.from(), r.to(), |
| 195 | List.of("code", "type", "value", "state", "uses", "discount", "orderTotal"), rows, totals(rows, 7, 4, 5, 6)); | |
| 196 | } | |
| 197 | ||
| 198 | /** Products on sale with this many or fewer in stock (default 5), emptiest first. A snapshot: no dates. */ | |
| 199 | ReportTable lowStock(Integer threshold) { | |
| 200 |
1
1. lowStock : removed conditional - replaced equality check with false → KILLED |
int t = threshold == null ? 5 : threshold; |
| 201 |
4
1. lowStock : removed conditional - replaced comparison check with false → KILLED 2. lowStock : changed conditional boundary → KILLED 3. lowStock : removed conditional - replaced comparison check with false → KILLED 4. lowStock : changed conditional boundary → KILLED |
if (t < 0 || t > 1000) throw new BusinessRuleException("threshold must be between 0 and 1000"); |
| 202 | List<List<Object>> rows = jdbc.query(""" | |
| 203 | select sku, name, category, stock, price from products | |
| 204 | where active = true and stock <= ? order by stock, id""", | |
| 205 |
1
1. lambda$lowStock$9 : replaced return value with Collections.emptyList for com/rbctcsworld/ecommerce/report/ReportService::lambda$lowStock$9 → KILLED |
(rs, i) -> Arrays.<Object>asList(rs.getString("sku"), rs.getString("name"), rs.getString("category"), |
| 206 | rs.getInt("stock"), money(rs.getBigDecimal("price"))), t); | |
| 207 |
1
1. lowStock : replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::lowStock → KILLED |
return new ReportTable("low-stock", null, null, List.of("sku", "name", "category", "stock", "price"), rows, null); |
| 208 | } | |
| 209 | ||
| 210 | /** What the stock on the shelves is worth, per category (products on sale). A snapshot: no dates. */ | |
| 211 | ReportTable inventory() { | |
| 212 | List<List<Object>> rows = jdbc.query(""" | |
| 213 | select coalesce(category, '(none)') as cat, count(*) as product_count, sum(stock) as unit_count, | |
| 214 | sum(price * stock) as stock_value | |
| 215 | from products where active = true | |
| 216 | group by coalesce(category, '(none)') order by stock_value desc, cat""", | |
| 217 |
1
1. lambda$inventory$10 : replaced return value with Collections.emptyList for com/rbctcsworld/ecommerce/report/ReportService::lambda$inventory$10 → KILLED |
(rs, i) -> List.<Object>of(rs.getString("cat"), rs.getLong("product_count"), rs.getLong("unit_count"), |
| 218 | money(rs.getBigDecimal("stock_value")))); | |
| 219 |
1
1. inventory : replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::inventory → KILLED |
return new ReportTable("inventory", null, null, List.of("category", "products", "units", "value"), rows, |
| 220 | totals(rows, 4, 1, 2, 3)); | |
| 221 | } | |
| 222 | ||
| 223 | /** Where the stock is: units and their value per warehouse (products on sale). A snapshot: no dates. */ | |
| 224 | ReportTable stockByWarehouse() { | |
| 225 | List<List<Object>> rows = jdbc.query(""" | |
| 226 | select w.code, w.city, w.state, w.active, coalesce(s.product_count, 0) as product_count, | |
| 227 | coalesce(s.unit_count, 0) as unit_count, coalesce(s.stock_value, 0) as stock_value | |
| 228 | from warehouses w left join ( | |
| 229 | select ws.warehouse_id, count(case when ws.quantity > 0 then 1 end) as product_count, | |
| 230 | sum(ws.quantity) as unit_count, sum(ws.quantity * p.price) as stock_value | |
| 231 | from warehouse_stock ws join products p on p.id = ws.product_id | |
| 232 | where p.active = true group by ws.warehouse_id) s on s.warehouse_id = w.id | |
| 233 | order by w.priority, w.id""", | |
| 234 |
1
1. lambda$stockByWarehouse$11 : replaced return value with Collections.emptyList for com/rbctcsworld/ecommerce/report/ReportService::lambda$stockByWarehouse$11 → KILLED |
(rs, i) -> List.<Object>of(rs.getString("code"), rs.getString("city"), rs.getString("state"), |
| 235 |
1
1. lambda$stockByWarehouse$11 : removed conditional - replaced equality check with false → KILLED |
rs.getBoolean("active") ? "ACTIVE" : "DISABLED", rs.getLong("product_count"), |
| 236 | rs.getLong("unit_count"), money(rs.getBigDecimal("stock_value")))); | |
| 237 |
1
1. stockByWarehouse : replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::stockByWarehouse → KILLED |
return new ReportTable("stock-by-warehouse", null, null, |
| 238 | List.of("warehouse", "city", "usState", "state", "products", "units", "value"), rows, totals(rows, 7, 5, 6)); | |
| 239 | } | |
| 240 | ||
| 241 | // ------------------------------------------------------------------ helpers | |
| 242 | ||
| 243 | /** Money always with 2 decimals (databases differ in the scale of SUM and COALESCE). */ | |
| 244 | static BigDecimal money(BigDecimal v) { | |
| 245 |
2
1. money : removed conditional - replaced equality check with false → SURVIVED 2. money : replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::money → KILLED |
return (v == null ? BigDecimal.ZERO : v).setScale(2, java.math.RoundingMode.HALF_UP); |
| 246 | } | |
| 247 | ||
| 248 | private static BigDecimal[] zeros(int n) { | |
| 249 | BigDecimal[] a = new BigDecimal[n]; | |
| 250 |
1
1. zeros : removed call to java/util/Arrays::fill → KILLED |
Arrays.fill(a, BigDecimal.ZERO); |
| 251 |
1
1. zeros : replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::zeros → KILLED |
return a; |
| 252 | } | |
| 253 | ||
| 254 | /** Label + the counts (orders, items) as whole numbers + the money columns with 2 decimals. */ | |
| 255 | private static List<Object> row(String label, BigDecimal[] p) { | |
| 256 | List<Object> row = new ArrayList<>(); | |
| 257 | row.add(label); | |
| 258 | row.add(p[0].longValue()); | |
| 259 | row.add(p[1].longValue()); | |
| 260 |
3
1. row : Changed increment from 1 to -1 → KILLED 2. row : changed conditional boundary → KILLED 3. row : removed conditional - replaced comparison check with false → KILLED |
for (int i = 2; i < p.length; i++) row.add(p[i].setScale(2, java.math.RoundingMode.HALF_UP)); |
| 261 |
1
1. row : replaced return value with Collections.emptyList for com/rbctcsworld/ecommerce/report/ReportService::row → KILLED |
return row; |
| 262 | } | |
| 263 | ||
| 264 | /** | |
| 265 | * The totals line: "total" in the first column, the sum of the given columns, null elsewhere. | |
| 266 | * width = number of columns; sums of whole numbers stay whole, money keeps 2 decimals. | |
| 267 | */ | |
| 268 | static List<Object> totals(List<List<Object>> rows, int width, int... summed) { | |
| 269 | List<Object> t = new ArrayList<>(java.util.Collections.nCopies(width, null)); | |
| 270 | t.set(0, "total"); | |
| 271 | for (int c : summed) { | |
| 272 |
2
1. lambda$totals$12 : replaced boolean return with false for com/rbctcsworld/ecommerce/report/ReportService::lambda$totals$12 → KILLED 2. lambda$totals$12 : replaced boolean return with true for com/rbctcsworld/ecommerce/report/ReportService::lambda$totals$12 → KILLED |
boolean money = rows.stream().anyMatch(r -> r.get(c) instanceof BigDecimal); |
| 273 | BigDecimal sum = BigDecimal.ZERO; | |
| 274 | for (List<Object> r : rows) sum = sum.add(new BigDecimal(r.get(c).toString())); | |
| 275 |
1
1. totals : removed conditional - replaced equality check with false → KILLED |
t.set(c, money ? sum.setScale(2, java.math.RoundingMode.HALF_UP) : (Object) sum.longValue()); |
| 276 | } | |
| 277 |
1
1. totals : replaced return value with Collections.emptyList for com/rbctcsworld/ecommerce/report/ReportService::totals → KILLED |
return t; |
| 278 | } | |
| 279 | } | |
Mutations | ||
| 58 |
1.1 |
|
| 59 |
1.1 |
|
| 75 |
1.1 |
|
| 76 |
1.1 |
|
| 77 |
1.1 |
|
| 89 |
1.1 |
|
| 90 |
1.1 |
|
| 91 |
1.1 |
|
| 92 |
1.1 2.2 3.3 |
|
| 95 |
1.1 |
|
| 102 |
1.1 2.2 |
|
| 103 |
1.1 2.2 |
|
| 105 |
1.1 |
|
| 106 |
1.1 |
|
| 108 |
1.1 |
|
| 112 |
1.1 |
|
| 115 |
1.1 |
|
| 126 |
1.1 |
|
| 128 |
1.1 2.2 3.3 |
|
| 130 |
1.1 |
|
| 136 |
1.1 |
|
| 137 |
1.1 2.2 3.3 4.4 |
|
| 146 |
1.1 |
|
| 149 |
1.1 |
|
| 156 |
1.1 |
|
| 157 |
1.1 |
|
| 162 |
1.1 2.2 |
|
| 163 |
1.1 |
|
| 174 |
1.1 |
|
| 177 |
1.1 |
|
| 190 |
1.1 |
|
| 191 |
1.1 |
|
| 194 |
1.1 |
|
| 200 |
1.1 |
|
| 201 |
1.1 2.2 3.3 4.4 |
|
| 205 |
1.1 |
|
| 207 |
1.1 |
|
| 217 |
1.1 |
|
| 219 |
1.1 |
|
| 234 |
1.1 |
|
| 235 |
1.1 |
|
| 237 |
1.1 |
|
| 245 |
1.1 2.2 |
|
| 250 |
1.1 |
|
| 251 |
1.1 |
|
| 260 |
1.1 2.2 3.3 |
|
| 261 |
1.1 |
|
| 272 |
1.1 2.2 |
|
| 275 |
1.1 |
|
| 277 |
1.1 |