srs/lib/core/models.dart
Aswin Biju 749d18192a
All checks were successful
deploy / deploy (push) Successful in 4m58s
refactor: updated UI and other trivial fixes
2026-11-05 10:13:32 +05:30

184 lines
4.2 KiB
Dart

import 'format.dart';
class AppUser {
const AppUser({
required this.id,
required this.username,
required this.isAdmin,
required this.active,
required this.shopIds,
this.phone,
this.sendResults = false,
});
final int id;
final String username;
final String? phone;
final bool isAdmin;
final bool active;
final List<int> shopIds;
final bool sendResults;
bool get getsResults => sendResults && active && phone != null;
}
class Shop {
const Shop({
required this.id,
required this.code,
required this.name,
this.active = true,
});
final int id;
final String code;
final String name;
final bool active;
Shop copyWith({String? name, bool? active}) => Shop(
id: id,
code: code,
name: name ?? this.name,
active: active ?? this.active,
);
}
class DrawInfo {
const DrawInfo({
required this.date,
required this.published,
this.scheme,
this.code,
this.hasWin = false,
});
final DateTime date;
final String? scheme;
final String? code;
final bool published;
final bool hasWin;
String get label => published ? '$scheme · $code' : 'No result yet';
}
class PrizeHit {
const PrizeHit({required this.tier, required this.amount});
final int tier;
final int amount;
}
class EndingQty {
const EndingQty({
required this.ending,
required this.qty,
this.hits = const [],
});
final String ending;
final int qty;
final List<PrizeHit> hits;
bool get wins => hits.isNotEmpty;
int get perTicket => hits.fold(0, (a, h) => a + h.amount);
int get prize => qty * perTicket;
String get tierText => tiersLabel([for (final h in hits) h.tier]);
}
class Order {
const Order({
required this.id,
required this.shop,
required this.drawDate,
required this.time,
required this.isPhoto,
required this.edited,
required this.lines,
this.rawText,
});
final int id;
final Shop shop;
final DateTime drawDate;
final DateTime time;
final bool isPhoto;
final bool edited;
final String? rawText;
final List<EndingQty> lines;
bool get hasText => (rawText ?? '').trim().isNotEmpty;
String get kind => isPhoto ? (hasText ? 'Photo + text' : 'Photo') : 'Text';
bool matches(String q) =>
q.isEmpty ||
shop.name.toLowerCase().contains(q) ||
shop.code.toLowerCase().contains(q) ||
(rawText ?? '').toLowerCase().contains(q) ||
lines.any((l) => l.ending.contains(q));
int get tickets => lines.fold(0, (a, l) => a + l.qty);
int get prize => lines.fold(0, (a, l) => a + l.prize);
int get winTickets => lines.where((l) => l.wins).fold(0, (a, l) => a + l.qty);
}
class ShopResult {
const ShopResult({
required this.shop,
required this.tickets,
required this.orders,
required this.winTickets,
required this.prize,
});
final Shop shop;
final int tickets;
final int orders;
final int winTickets;
final int prize;
}
class DrawResults {
const DrawResults({required this.draw, required this.shops});
final DrawInfo draw;
final List<ShopResult> shops;
int get totalPrize => shops.fold(0, (a, s) => a + s.prize);
int get winningTickets => shops.fold(0, (a, s) => a + s.winTickets);
int get totalTickets => shops.fold(0, (a, s) => a + s.tickets);
int get orders => shops.fold(0, (a, s) => a + s.orders);
int get winningShops => shops.where((s) => s.prize > 0).length;
ShopResult? get topShop =>
shops.isNotEmpty && shops.first.prize > 0 ? shops.first : null;
}
class ShopDay {
const ShopDay({
required this.shop,
required this.tickets,
required this.orders,
required this.endings,
});
final Shop shop;
final int tickets;
final int orders;
final int endings;
}
class ShopDetail {
const ShopDetail({
required this.shop,
required this.draw,
required this.endings,
required this.orders,
});
final Shop shop;
final DrawInfo draw;
final List<EndingQty> endings;
final List<Order> orders;
int get tickets => endings.fold(0, (a, e) => a + e.qty);
List<EndingQty> get wins => endings.where((e) => e.wins).toList();
int get winTickets => wins.fold(0, (a, e) => a + e.qty);
int get prize => wins.fold(0, (a, e) => a + e.prize);
}