ReportService.java

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
Location : run
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:theRangeIsCheckedAndOneDayIsAllowed()]
removed conditional - replaced equality check with false → KILLED

59

1.1
Location : run
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:lowStockIsASnapshotOfProductsOnSale()]
replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::run → KILLED

75

1.1
Location : csv
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:csvHasTheHeaderTheRowsAndTheTotals()]
removed call to java/util/List::forEach → KILLED

76

1.1
Location : csv
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:csvHasTheHeaderTheRowsAndTheTotals()]
removed conditional - replaced equality check with false → KILLED

77

1.1
Location : csv
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:csvHasTheHeaderTheRowsAndTheTotals()]
replaced return value with "" for com/rbctcsworld/ecommerce/report/ReportService::csv → KILLED

89

1.1
Location : range
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:topProductsByUnitsThenMoney()]
removed conditional - replaced equality check with false → KILLED

90

1.1
Location : range
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:topProductsByUnitsThenMoney()]
removed conditional - replaced equality check with false → KILLED

91

1.1
Location : range
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:theRangeIsCheckedAndOneDayIsAllowed()]
removed conditional - replaced equality check with false → KILLED

92

1.1
Location : range
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:theRangeIsCheckedAndOneDayIsAllowed()]
Replaced long addition with subtraction → KILLED

2.2
Location : range
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:theRangeIsCheckedAndOneDayIsAllowed()]
changed conditional boundary → KILLED

3.3
Location : range
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:theRangeIsCheckedAndOneDayIsAllowed()]
removed conditional - replaced comparison check with false → KILLED

95

1.1
Location : range
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:salesPerDayCountOnlyMoneyReceivedOnThePaymentDayAndListQuietDays()]
replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::range → KILLED

102

1.1
Location : sales
Killed by : none
removed conditional - replaced equality check with false → SURVIVED
Covering tests

2.2
Location : sales
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:salesPerMonthAndTheDefaultRangeIsTheLast30Days()]
removed conditional - replaced equality check with false → KILLED

103

1.1
Location : sales
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:salesPerMonthAndTheDefaultRangeIsTheLast30Days()]
removed conditional - replaced equality check with false → KILLED

2.2
Location : sales
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:salesPerMonthAndTheDefaultRangeIsTheLast30Days()]
removed conditional - replaced equality check with false → KILLED

105

1.1
Location : sales
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:salesPerDayCountOnlyMoneyReceivedOnThePaymentDayAndListQuietDays()]
removed conditional - replaced equality check with false → KILLED

106

1.1
Location : sales
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:salesPerDayCountOnlyMoneyReceivedOnThePaymentDayAndListQuietDays()]
removed conditional - replaced equality check with false → KILLED

108

1.1
Location : sales
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:salesPerMonthAndTheDefaultRangeIsTheLast30Days()]
removed conditional - replaced equality check with false → KILLED

112

1.1
Location : sales
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:salesPerDayCountOnlyMoneyReceivedOnThePaymentDayAndListQuietDays()]
removed call to org/springframework/jdbc/core/JdbcTemplate::query → KILLED

115

1.1
Location : lambda$sales$1
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:salesPerDayCountOnlyMoneyReceivedOnThePaymentDayAndListQuietDays()]
removed conditional - replaced equality check with false → KILLED

126

1.1
Location : sales
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:salesPerDayCountOnlyMoneyReceivedOnThePaymentDayAndListQuietDays()]
removed call to java/util/Map::forEach → KILLED

128

1.1
Location : lambda$sales$2
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:salesPerDayCountOnlyMoneyReceivedOnThePaymentDayAndListQuietDays()]
changed conditional boundary → KILLED

2.2
Location : lambda$sales$2
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:salesPerDayCountOnlyMoneyReceivedOnThePaymentDayAndListQuietDays()]
Changed increment from 1 to -1 → KILLED

3.3
Location : lambda$sales$2
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:salesPerDayCountOnlyMoneyReceivedOnThePaymentDayAndListQuietDays()]
removed conditional - replaced comparison check with false → KILLED

130

1.1
Location : sales
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:salesPerDayCountOnlyMoneyReceivedOnThePaymentDayAndListQuietDays()]
replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::sales → KILLED

136

1.1
Location : topProducts
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:topProductsByUnitsThenMoney()]
removed conditional - replaced equality check with false → KILLED

137

1.1
Location : topProducts
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:topProductsByUnitsThenMoney()]
changed conditional boundary → KILLED

2.2
Location : topProducts
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:topProductsByUnitsThenMoney()]
removed conditional - replaced comparison check with false → KILLED

3.3
Location : topProducts
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:topProductsByUnitsThenMoney()]
changed conditional boundary → KILLED

4.4
Location : topProducts
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:topProductsByUnitsThenMoney()]
removed conditional - replaced comparison check with false → KILLED

146

1.1
Location : lambda$topProducts$3
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:topProductsByUnitsThenMoney()]
replaced return value with Collections.emptyList for com/rbctcsworld/ecommerce/report/ReportService::lambda$topProducts$3 → KILLED

149

1.1
Location : topProducts
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:topProductsByUnitsThenMoney()]
replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::topProducts → KILLED

156

1.1
Location : ordersByStatus
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:ordersByStatusInLifecycleOrderWithEmptyStatusesListed()]
removed call to java/util/List::forEach → KILLED

157

1.1
Location : ordersByStatus
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:ordersByStatusInLifecycleOrderWithEmptyStatusesListed()]
removed call to org/springframework/jdbc/core/JdbcTemplate::query → KILLED

162

1.1
Location : ordersByStatus
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:ordersByStatusInLifecycleOrderWithEmptyStatusesListed()]
removed call to java/util/Map::forEach → KILLED

2.2
Location : lambda$ordersByStatus$6
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:ordersByStatusInLifecycleOrderWithEmptyStatusesListed()]
removed conditional - replaced equality check with false → KILLED

163

1.1
Location : ordersByStatus
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:ordersByStatusInLifecycleOrderWithEmptyStatusesListed()]
replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::ordersByStatus → KILLED

174

1.1
Location : lambda$returns$7
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:returnsByReasonAndDecision()]
replaced return value with Collections.emptyList for com/rbctcsworld/ecommerce/report/ReportService::lambda$returns$7 → KILLED

177

1.1
Location : returns
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:returnsByReasonAndDecision()]
replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::returns → KILLED

190

1.1
Location : lambda$coupons$8
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:couponsWithTheirUseExcludingCancelledOrders()]
replaced return value with Collections.emptyList for com/rbctcsworld/ecommerce/report/ReportService::lambda$coupons$8 → KILLED

191

1.1
Location : lambda$coupons$8
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:couponsWithTheirUseExcludingCancelledOrders()]
removed conditional - replaced equality check with false → KILLED

194

1.1
Location : coupons
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:couponsWithTheirUseExcludingCancelledOrders()]
replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::coupons → KILLED

200

1.1
Location : lowStock
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:lowStockIsASnapshotOfProductsOnSale()]
removed conditional - replaced equality check with false → KILLED

201

1.1
Location : lowStock
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:lowStockIsASnapshotOfProductsOnSale()]
removed conditional - replaced comparison check with false → KILLED

2.2
Location : lowStock
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:lowStockIsASnapshotOfProductsOnSale()]
changed conditional boundary → KILLED

3.3
Location : lowStock
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:lowStockIsASnapshotOfProductsOnSale()]
removed conditional - replaced comparison check with false → KILLED

4.4
Location : lowStock
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:lowStockIsASnapshotOfProductsOnSale()]
changed conditional boundary → KILLED

205

1.1
Location : lambda$lowStock$9
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:lowStockIsASnapshotOfProductsOnSale()]
replaced return value with Collections.emptyList for com/rbctcsworld/ecommerce/report/ReportService::lambda$lowStock$9 → KILLED

207

1.1
Location : lowStock
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:lowStockIsASnapshotOfProductsOnSale()]
replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::lowStock → KILLED

217

1.1
Location : lambda$inventory$10
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:inventoryValuePerCategory()]
replaced return value with Collections.emptyList for com/rbctcsworld/ecommerce/report/ReportService::lambda$inventory$10 → KILLED

219

1.1
Location : inventory
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:inventoryValuePerCategory()]
replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::inventory → KILLED

234

1.1
Location : lambda$stockByWarehouse$11
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:stockByWarehouseShowsWhereTheUnitsAndTheirValueAre()]
replaced return value with Collections.emptyList for com/rbctcsworld/ecommerce/report/ReportService::lambda$stockByWarehouse$11 → KILLED

235

1.1
Location : lambda$stockByWarehouse$11
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:stockByWarehouseShowsWhereTheUnitsAndTheirValueAre()]
removed conditional - replaced equality check with false → KILLED

237

1.1
Location : stockByWarehouse
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:stockByWarehouseShowsWhereTheUnitsAndTheirValueAre()]
replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::stockByWarehouse → KILLED

245

1.1
Location : money
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:lowStockIsASnapshotOfProductsOnSale()]
replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::money → KILLED

2.2
Location : money
Killed by : none
removed conditional - replaced equality check with false → SURVIVED
Covering tests

250

1.1
Location : zeros
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:salesPerDayCountOnlyMoneyReceivedOnThePaymentDayAndListQuietDays()]
removed call to java/util/Arrays::fill → KILLED

251

1.1
Location : zeros
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:salesPerDayCountOnlyMoneyReceivedOnThePaymentDayAndListQuietDays()]
replaced return value with null for com/rbctcsworld/ecommerce/report/ReportService::zeros → KILLED

260

1.1
Location : row
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:salesPerDayCountOnlyMoneyReceivedOnThePaymentDayAndListQuietDays()]
Changed increment from 1 to -1 → KILLED

2.2
Location : row
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:salesPerDayCountOnlyMoneyReceivedOnThePaymentDayAndListQuietDays()]
changed conditional boundary → KILLED

3.3
Location : row
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:salesPerDayCountOnlyMoneyReceivedOnThePaymentDayAndListQuietDays()]
removed conditional - replaced comparison check with false → KILLED

261

1.1
Location : row
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:salesPerDayCountOnlyMoneyReceivedOnThePaymentDayAndListQuietDays()]
replaced return value with Collections.emptyList for com/rbctcsworld/ecommerce/report/ReportService::row → KILLED

272

1.1
Location : lambda$totals$12
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:inventoryValuePerCategory()]
replaced boolean return with false for com/rbctcsworld/ecommerce/report/ReportService::lambda$totals$12 → KILLED

2.2
Location : lambda$totals$12
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:inventoryValuePerCategory()]
replaced boolean return with true for com/rbctcsworld/ecommerce/report/ReportService::lambda$totals$12 → KILLED

275

1.1
Location : totals
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:inventoryValuePerCategory()]
removed conditional - replaced equality check with false → KILLED

277

1.1
Location : totals
Killed by : com.rbctcsworld.ecommerce.report.ReportServiceTest.[engine:junit-jupiter]/[class:com.rbctcsworld.ecommerce.report.ReportServiceTest]/[method:inventoryValuePerCategory()]
replaced return value with Collections.emptyList for com/rbctcsworld/ecommerce/report/ReportService::totals → KILLED

Active mutators

Tests examined


Report generated by PIT 1.30.0 support