2023-12-21 09:14:40 +00:00
|
|
|
import 'dart:async';
|
|
|
|
|
|
|
|
|
|
import 'package:guru_app/financial/igc/igc_manager.dart';
|
|
|
|
|
import 'package:guru_app/financial/product/product_model.dart';
|
2024-03-07 03:46:50 +00:00
|
|
|
import 'package:guru_app/inventory/inventory_manager.dart';
|
2023-12-21 09:14:40 +00:00
|
|
|
import 'manifest.dart';
|
|
|
|
|
|
|
|
|
|
/// Created by Haoyi on 2022/8/21
|
|
|
|
|
|
2024-03-07 03:46:50 +00:00
|
|
|
// typedef DetailsDistributor = Future<bool> Function(Details, TransactionMethod, String scene);
|
|
|
|
|
|
|
|
|
|
typedef DetailsDistributor = Future<List<StockItem>> Function(
|
|
|
|
|
Details, TransactionMethod, String scene);
|
2023-12-21 09:14:40 +00:00
|
|
|
|
|
|
|
|
typedef ManifestBuilder = Future<Manifest?> Function(TransactionIntent);
|
|
|
|
|
|
|
|
|
|
class ManifestManager {
|
|
|
|
|
ManifestManager._() {
|
|
|
|
|
observableDeliveredManifest = deliveredManifestStream.stream.asBroadcastStream();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final StreamController<Manifest> deliveredManifestStream = StreamController();
|
|
|
|
|
|
|
|
|
|
static final ManifestManager instance = ManifestManager._();
|
|
|
|
|
|
|
|
|
|
late Stream<Manifest> observableDeliveredManifest;
|
|
|
|
|
|
|
|
|
|
final Map<String, DetailsDistributor> distributors = {
|
|
|
|
|
DetailsReservedType.igc: _deliverIgcDetails
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
final List<ManifestBuilder> builders = [];
|
|
|
|
|
|
2024-03-07 03:46:50 +00:00
|
|
|
static Future<List<StockItem>> _deliverIgcDetails(
|
2023-12-21 09:14:40 +00:00
|
|
|
Details details, TransactionMethod method, String scene) async {
|
|
|
|
|
if (details.amount > 0) {
|
2024-03-07 03:46:50 +00:00
|
|
|
await IgcManager.instance.accumulate(details.amount, method, scene: scene);
|
2023-12-21 09:14:40 +00:00
|
|
|
}
|
2024-03-07 03:46:50 +00:00
|
|
|
return [];
|
2023-12-21 09:14:40 +00:00
|
|
|
}
|
|
|
|
|
|
2024-03-07 03:46:50 +00:00
|
|
|
static Future<List<StockItem>> _deliverDefaultDetails(
|
|
|
|
|
Details details, TransactionMethod method, String scene) async {
|
|
|
|
|
if (details.amount > 0) {
|
|
|
|
|
return [StockItem.fromDetails(details)];
|
|
|
|
|
}
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// static Future<bool> _deliverDetails(
|
|
|
|
|
// Details details, TransactionMethod method, String scene) async {
|
|
|
|
|
// final stock = StockItem.fromDetails(details);
|
|
|
|
|
// if (stock.amount > 0) {
|
|
|
|
|
// await InventoryManager.instance.acquire([stock], method, scene);
|
|
|
|
|
// }
|
|
|
|
|
// return false;
|
|
|
|
|
// }
|
|
|
|
|
|
2023-12-21 09:14:40 +00:00
|
|
|
void addDistributor(String type, DetailsDistributor distributor) {
|
|
|
|
|
distributors[type] = distributor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void addBuilder(ManifestBuilder builder) {
|
|
|
|
|
builders.add(builder);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void addBuilders(List<ManifestBuilder> builders) {
|
|
|
|
|
this.builders.addAll(builders);
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-07 03:46:50 +00:00
|
|
|
Future _acquire(List<StockItem> items, TransactionMethod method, Manifest manifest) async {
|
|
|
|
|
if (items.isNotEmpty) {
|
|
|
|
|
String specific = "";
|
|
|
|
|
switch (method) {
|
|
|
|
|
case TransactionMethod.iap:
|
|
|
|
|
specific = manifest.contentId;
|
|
|
|
|
break;
|
|
|
|
|
case TransactionMethod.igc:
|
|
|
|
|
specific = "coin";
|
|
|
|
|
break;
|
|
|
|
|
case TransactionMethod.igb:
|
|
|
|
|
specific = manifest.barterId;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
specific = manifest.scene;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
await InventoryManager.instance.acquire(items, method, specific, scene: manifest.scene);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<List<StockItem>> deliverStockItems(
|
|
|
|
|
List<StockItem> items, Manifest manifest, TransactionMethod method) async {
|
|
|
|
|
final List<StockItem> unsold = [];
|
|
|
|
|
for (var item in items) {
|
|
|
|
|
if (item.sku == DetailsReservedType.igc) {
|
|
|
|
|
await distributors[DetailsReservedType.igc]
|
|
|
|
|
?.call(Details.define(DetailsReservedType.igc, item.amount), method, manifest.scene);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
unsold.add(item);
|
|
|
|
|
}
|
|
|
|
|
return unsold;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-21 09:14:40 +00:00
|
|
|
Future<bool> deliver(Manifest manifest, TransactionMethod method) async {
|
|
|
|
|
bool result = false;
|
2024-03-07 03:46:50 +00:00
|
|
|
final List<StockItem> unsold = [];
|
2023-12-21 09:14:40 +00:00
|
|
|
for (var details in manifest.details) {
|
2024-03-07 03:46:50 +00:00
|
|
|
final items = await distributors[details.type]?.call(details, method, manifest.scene) ??
|
|
|
|
|
await _deliverDefaultDetails(details, method, manifest.scene);
|
|
|
|
|
final unsoldItems = await deliverStockItems(items, manifest, method);
|
|
|
|
|
unsold.addAll(unsoldItems);
|
|
|
|
|
result |= unsoldItems.isEmpty;
|
|
|
|
|
}
|
|
|
|
|
if (unsold.isNotEmpty) {
|
|
|
|
|
await _acquire(unsold, method, manifest);
|
2023-12-21 09:14:40 +00:00
|
|
|
}
|
2024-03-07 03:46:50 +00:00
|
|
|
|
2023-12-21 09:14:40 +00:00
|
|
|
deliveredManifestStream.add(manifest);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<Manifest> createManifest(TransactionIntent intent) async {
|
|
|
|
|
for (var builder in builders) {
|
|
|
|
|
final manifest = await builder(intent);
|
|
|
|
|
if (manifest != null) {
|
|
|
|
|
return manifest;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return Manifest.empty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Manifest createIgcManifest(int igc, {String? category, String scene = ""}) {
|
|
|
|
|
final details = <Details>[];
|
|
|
|
|
details.add(Details.define(DetailsReservedType.igc, igc));
|
|
|
|
|
|
|
|
|
|
final extras = <String, dynamic>{ExtraReservedField.scene: scene};
|
|
|
|
|
return Manifest(category ?? DetailsReservedType.igc, extras: extras, details: details);
|
|
|
|
|
}
|
2024-03-07 03:46:50 +00:00
|
|
|
|
|
|
|
|
// Manifest createIgbManifest(int igc, {String? category, String scene = ""}) {
|
|
|
|
|
// final details = <Details>[];
|
|
|
|
|
// details.add(Details.define(DetailsReservedType.igc, igc));
|
|
|
|
|
//
|
|
|
|
|
// final extras = <String, dynamic>{ExtraReservedField.scene: scene};
|
|
|
|
|
// return Manifest(category ?? DetailsReservedType.igc, extras: extras, details: details);
|
|
|
|
|
// }
|
2023-12-21 09:14:40 +00:00
|
|
|
}
|