feat(handover): one hand-over sheet replaces the separate sale/plantare doors
'Seeds changed hands' is now the single entry point on the variety detail (and per lot row): direction (gave/received), one-tap 'all of it' (default — the whole-plant/shrub case), optional partial quantity, counterparty, and reveal-on-tap money and return-promise sections that spawn the Sale/Plantare rows through recordHandover in one save. Zero-lot varieties still work (ledger rows only); several lots get a chip picker. The Sales/Plantares screens keep their own add buttons for off-app records — the sheets stay, demoted to secondary. i18n handover block in en/es/pt/ast; widget tests for the flow.
This commit is contained in:
parent
e6e70e4b97
commit
491e079b50
12 changed files with 849 additions and 152 deletions
143
apps/app_seeds/test/ui/handover_sheet_test.dart
Normal file
143
apps/app_seeds/test/ui/handover_sheet_test.dart
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
import 'package:commons_core/commons_core.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:tane/db/database.dart';
|
||||
import 'package:tane/db/enums.dart';
|
||||
|
||||
import '../support/test_support.dart';
|
||||
|
||||
void main() {
|
||||
late AppDatabase db;
|
||||
|
||||
setUp(() => db = newTestDatabase());
|
||||
tearDown(() => db.close());
|
||||
|
||||
testWidgets('the detail screen offers ONE hand-over door, no separate '
|
||||
'sale/plantare buttons', (tester) async {
|
||||
final repo = newTestRepository(db);
|
||||
final id = await repo.addQuickVariety(label: 'Maize');
|
||||
|
||||
await tester.pumpWidget(
|
||||
wrapDetail(
|
||||
repository: repo,
|
||||
varietyId: id,
|
||||
species: newTestSpeciesRepository(db),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('detail.handover')), findsOneWidget);
|
||||
expect(find.byKey(const Key('detail.addSale')), findsNothing);
|
||||
expect(find.byKey(const Key('detail.addPlantare')), findsNothing);
|
||||
await disposeTree(tester);
|
||||
});
|
||||
|
||||
testWidgets('giving all with payment and promise records the three pieces '
|
||||
'in one save', (tester) async {
|
||||
final repo = newTestRepository(db);
|
||||
final id = await repo.addQuickVariety(label: 'Maize');
|
||||
final lotId = await repo.addLot(
|
||||
varietyId: id,
|
||||
quantity: const Quantity(kind: QuantityKind.grams, count: 40),
|
||||
offerStatus: OfferStatus.sell,
|
||||
priceAmount: 3,
|
||||
priceCurrency: '€',
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
wrapDetail(
|
||||
repository: repo,
|
||||
varietyId: id,
|
||||
species: newTestSpeciesRepository(db),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.byKey(const Key('detail.handover')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// "All of it" is the default — one tap covers the whole-plant case.
|
||||
final allChip = tester.widget<ChoiceChip>(
|
||||
find.byKey(const Key('handover.allOfIt')),
|
||||
);
|
||||
expect(allChip.selected, isTrue);
|
||||
|
||||
await tester.enterText(
|
||||
find.byKey(const Key('handover.counterparty')),
|
||||
'María',
|
||||
);
|
||||
|
||||
await tester.tap(find.byKey(const Key('handover.addPayment')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.enterText(find.byKey(const Key('handover.amount')), '2,5');
|
||||
await tester.tap(find.byKey(const Key('handover.currencyChip.Ğ1')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.byKey(const Key('handover.addPromise')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.enterText(
|
||||
find.byKey(const Key('handover.owed')),
|
||||
'un puñado',
|
||||
);
|
||||
|
||||
await tester.ensureVisible(find.byKey(const Key('handover.save')));
|
||||
await tester.tap(find.byKey(const Key('handover.save')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final sales = await repo.watchSales().first;
|
||||
expect(sales.single.direction, SaleDirection.iSold);
|
||||
expect(sales.single.amount, 2.5);
|
||||
expect(sales.single.currency, 'Ğ1');
|
||||
expect(sales.single.counterparty, 'María');
|
||||
|
||||
final plantares = await repo.watchPlantares().first;
|
||||
expect(plantares.single.direction, PlantareDirection.owedToMe);
|
||||
expect(plantares.single.owedDescription, 'un puñado');
|
||||
|
||||
final lot = await (db.select(
|
||||
db.lots,
|
||||
)..where((l) => l.id.equals(lotId))).getSingle();
|
||||
expect(lot.quantityPrecise, 0);
|
||||
expect(lot.offerStatus, OfferStatus.private);
|
||||
expect(lot.priceAmount, isNull);
|
||||
|
||||
final movements = await db.select(db.movements).get();
|
||||
expect(movements.single.type, MovementType.given);
|
||||
expect(movements.single.plantareId, plantares.single.id);
|
||||
await disposeTree(tester);
|
||||
});
|
||||
|
||||
testWidgets('receiving hides the how-much choice and mirrors directions', (
|
||||
tester,
|
||||
) async {
|
||||
final repo = newTestRepository(db);
|
||||
final id = await repo.addQuickVariety(label: 'Maize');
|
||||
await repo.addLot(varietyId: id);
|
||||
|
||||
await tester.pumpWidget(
|
||||
wrapDetail(
|
||||
repository: repo,
|
||||
varietyId: id,
|
||||
species: newTestSpeciesRepository(db),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.byKey(const Key('detail.handover')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(
|
||||
find.byKey(const Key('handover.direction.iReceived')),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byKey(const Key('handover.allOfIt')), findsNothing);
|
||||
|
||||
await tester.ensureVisible(find.byKey(const Key('handover.save')));
|
||||
await tester.tap(find.byKey(const Key('handover.save')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final movements = await db.select(db.movements).get();
|
||||
expect(movements.single.type, MovementType.received);
|
||||
await disposeTree(tester);
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue