Select Join two table Header Detail Floor Orm in Flutter - flutter

I try to select two table header and detail use join select.
and what object/list return value from query ?
I used Floor ORM in flutter, but when I generate not success
these my class model and Dao
flutter pub run build_runner build
[INFO] Running build...
[INFO] 1.0s elapsed, 0/2 actions completed.
[INFO] 2.1s elapsed, 0/2 actions completed.
[INFO] 8.4s elapsed, 0/2 actions completed.
[SEVERE] floor_generator:floor_generator on lib/database/Database.dart:
ERORR
Can not define return type
package:myapp_sfaf/database/dao/SalesOrderDao.dart:35:16
╷
35 │ Future<List> getListHeaderDetailByIdHso(String idHso);
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^
╵
[INFO] Running build completed, took 8.8s
[INFO] Caching finalized dependency graph...
[INFO] Caching finalized dependency graph completed, took 59ms
[SEVERE] Failed after 8.8s
pub finished with exit code 1
class SalesOrderHd.dart
import 'package:floor/floor.dart';
import 'package:myapp_sfaf/database/entity/Customer.dart';
import 'package:myapp_sfaf/database/entity/Salesman.dart';
#Entity(tableName: 'thd_so',
indices: [Index(value: ['docCode'],unique: true)],
foreignKeys: [
ForeignKey(
childColumns: ['idCust'],
parentColumns: ['custId'],
entity: Customer,
onDelete: ForeignKeyAction.restrict
),
ForeignKey(
childColumns: ['idSals'],
parentColumns: ['idSalesman'],
entity: Salesman,
onDelete: ForeignKeyAction.restrict
)
]
)
class SalesOrderHd {
#primaryKey
final String idHso;
final String custCode;
final String custName;
final String address;
final String docCode;
SalesOrderHd(
this.idHso, this.custCode, this.custName, this.address, this.docCode
);
}
class SalesOrderDt.dart
import 'package:floor/floor.dart';
import 'package:myapp_sfaf/database/entity/ProductItem.dart';
import 'package:myapp_sfaf/database/entity/SalesOrderHd.dart';
#Entity(tableName: 'tdd_so')
class SalesOrderDt {
#primaryKey
final String id;
final String docCode;
final String itemCode;
final String itemName;
SalesOrderDt(
this.id,this.docCode, this.itemCode, this.itemName
);
}
SalesOrderDao.dart
#dao
abstract class SalesOrderDao {
#Query('SELECT hd.custName,hd.address, dt.itemCode, dt.itemName FROM thd_so hd
left join tdd_so dt WHERE hd.docCode = dt.docCode AND hd.idHso = :idHso')
Future<List> getListHeaderDetailByIdHso(String idHso);
}
whether the Query is wrong or because the return value is not written by me,
I want the return value of the query to be a List Object Model.
thank you for your help,

problem solved i use #DatabaseView.
i make one class .dart file
#DatabaseView('SELECT thd_so.custName, thd_so.address, tdd_so.itemCode,
tdd_so.itemName FROM thd_so, tdd_so
WHERE thd_so.docCode == tdd_so.docCode ',
viewName: 'myJoinedObject')
class MyJoinedObject{
String custName;
String address;
String itemCode;
String itemName;
MyJoinedObject(this.custName, this.address, this.itemCode,
this.itemName);
}
in Dao file
#Query('SELECT * FROM MyJoinedObject')
Stream<List<MyJoinedObject?>> getStreamedStuff();
used
getStreamedStuff(){
Stream<List<MyJoinedObject?>> list =
_salesOrderRepository.getStreamedStuff();
list.forEach((element) {
print('${element.elementAt(0)!.itemCode}');
print('CustName nya ${element.elementAt(0)!.custName}');
);
}
);
}

Related

How to make #factoryParams nullable in dart/Flutter?

I'm trying to use the #factoryParam annotation of injectable package by using it in a class. But whenever I try to run the build runner to generate the config file, it gives me an error saying the Factory params must be nullable.
import 'package:injectable/injectable.dart';
#injectable
class QuoteRepository {
const QuoteRepository(
#factoryParam String env)
: _env = env;
final String _env;
String getQuotes() {
return _env;
}
}
Error:
[SEVERE] injectable_generator:injectable_builder on features/testing_view_model.dart:
Factory params must be nullable
package:features/testing_view_model.dart:6:28
╷
6 │ #factoryParam String env)
│ ^^^
Try changing it to String? This will enable a String to be able to accept a null value also

storing a nested data structure in ObjectBox with type conversion method (.toObjectBox)

I guess the best (only?) way is to create a separate box for the nested structure and then to create a relation from parent (ONE) to children (MANY).
However, my issue is how to implement a .toObjectBox() method to convert my domain data model into the ObjectBox data model. Is there anything alike Either from the dartz package (returns either a left or a right side object), which transports 2 objects simultaneously?
So with the ObjectBox Entities
#Entity()
class Customer {
int id;
#Backlink('customer')
final orders = ToMany<Order>();
}
#Entity()
class Order {
int id;
final customer = ToOne<Customer>();
}
I would store the parent (customer) with the nested data objected (order) in the 2 related boxes
Customer customer = domainData.toObjectBox; // but how to get the order out?
customer.orders.add(Order('Order 1')); // shouldn't this be Order(1)?
final customerId = store.box<Customer>().put(customer);
This is how I typically implement the toObjectBox method. By here, you see that this does not work out because I would have to split parent and nested child apart. While I guess I could achieve this with some spaghetti, I wonder if there is a smart way of doing so since I guess this should be a common pattern (though I haven't found any Q&A on it).
#Entity()
Customer {
int id;
List<Order> orders;
Customer({required this.id, required this.orders});
CustomerObox toObjectBox() {
return CustomerObox(
id: id,
// orders: orders.map((x) => x.toObjectBox()).toList()
);
}
=== UPDATE =====================================
I have meanwhile tried to create a return structure myself, and now I am in the process to get this working.
class Pair<T1, T2> {
final T1 parent;
final T2 child;
Pair({required this.parent, required this.child});
}
#Entity()
class Customer {
int id;
List<Order> orders;
Customer({required this.id, required this.orders});
static Pair<CustomerObox, List<OrderObox>> toObjectBox(Customer cust) {
Pair<CustomerObox, List<OrderObox>>(
parent: CustomerObox(
id: cust.id,
),
child: cust.orders.map((o) => o.toObjectBox()).toList()
);
}
}
So I implemented toObjectBox as shown in the update of my question above.
Inside my local datasource implementation (I use the layers: presentation > business logic (bloc) > domain (models, contracts etc) > repository > datasource) I implemented the following methods
#override
Future<void> storeCustomer(Customer customer) async {
// Pair(T1 parent, T2 child) with T2 being List<OrderObox>
final Pair customerObox = Customer.toObjectBox(customer);
final CustomerObox customerParent = customerObox.parent;
final List<OrderObox> customerChildren = customerObox.child;
for (final child in customerChildren)
customerParent.records.add(child);
// puts both, parent and children:
final id = _sBox.put(customerParent);
}
#override
Future<List<Customer>> getAllCustomers() async {
final List<Customer> parents = [];
final List<CustomerObox> parentsObox = await _sBox.getAll();
for (final p in parentsObox) {
final List<CustomerObox> childrenObox = p.records;
parents.add(SessionJournalDto.fromObjectBox(p));
for (final c in childrenObox)
parents.last.records.add(Order.fromObjectBox(c));
}
return parents;
}

Flutter-moor generator problem with build-runner

Whenever I try to run flutter packages pub run build_runner watch I get this error message in the Terminal
Failed to precompile build_runner:build_runner:
/C:/src/flutter/.pub-cache/hosted/pub.dartlang.org/dart_style-1.3.3/lib/src/dart_formatter.dart:105:30: Error: Too
many positional arguments: 0 allowed, but 1 found.
Try removing the extra positional arguments.
scanner.configureFeatures(featureSet);
^
pub finished with exit code 1
this happend after i update moor_flutter plugin from ^1.6.0 => ^ 3.0.0
There is no errors with the older plugin
This is my code
import 'package:moor_flutter/moor_flutter.dart';
part 'Database.g.dart';
class Users extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get name => text().withLength(min:1,max:50)();
TextColumn get mobile => text().withLength(min:1,max:25)();
DateTimeColumn get birthdate => dateTime()();
}
#UseMoor(tables : [Users ],daos:[UserDao])
class AppDatabase extends _$AppDatabase {
AppDatabase():super(FlutterQueryExecutor.inDatabaseFolder(path: 'db.sqlite',
logStatements: true));
#override
int get schemaVersion =>1;
}
#UseDao(tables:[Users ],)
class UserDao extends DatabaseAccessor<AppDatabase> with _$UserDaoMixin{
final AppDatabase db;
UserDao(this.db):super(db);
Future <List<User>> getAllUsers() => select(users).get();
Stream <List<User>> watchAllUsers() {
return (select(users)
..orderBy([
(p)=> OrderingTerm(expression:p.id,mode:OrderingMode.desc ),
// (p)=> OrderingTerm(expression:p.id,mode:Ordering.desc )
])
)
.watch();
}
Stream <List<User>> watchUsersByName(String txt) {
String qu="SELECT * FROM users where ";
for (int i = 0; i < txt.length-1; i++){
String c = txt[i];
qu=qu+"name like '%"+c+"%' and ";
}
qu=qu+"name like '%"+txt[txt.length-1]+"%' ORDER BY id DESC";
return customSelectStream(
qu,readsFrom: {users}
).map((rows){
return rows.map((row) => User.fromData(row.data,db)).toList();
});
}
Future insertUser(Insertable<User> user) => into(users).insert(user);
Future updateUser(Insertable<User> user) => update(users).replace(user);
Future deleteUser(Insertable<User> user) => delete(users).delete(user);
}
the vs code gives me errors in the Appdatabase constructor and customselectstream function but
I searched the example in their Github repository and found the Appdatabase constructor is the same as mine.
The problem still presists after I commented the watchusersbyname also I tried to remove the arguments from super in the Appdatabase constructor but nothing changed
so can you please tell me what is the problem?
Thanks in advance.
Here is the one command which you need to run and check for the solution
flutter pub upgrade

How to deserialize Date ISO String to DateTime Object in built_value serialization in dart?

I wanna serialize a json object including an ISOString date to a dart object using built value.
this is a sample json:
{
"title": "test",
"description": "test description",
"date": "2020-06-05T11:42:38.585Z",
"creator": {
"email": "test#test.com"
}
}
this is the model:
abstract class Post implements Built<Post, PostBuilder> {
#nullable
#BuiltValueField(wireName: '_id')
String get id;
String get title;
String get description;
DateTime get date;
#nullable
User get creator;
Post._();
static Serializer<Post> get serializer => _$postSerializer;
factory Post([updates(PostBuilder b)]) = _$Post;
factory Post.fromJson(Map<String, dynamic> map) =>
serializers.deserializeWith(Post.serializer, map);
Map<String, dynamic> toJson() =>
serializers.serializeWith(Post.serializer, this);
}
and this is the error:
Deserializing '[title, test1, description, test1 description, date, 2020-06-05T...' to
'Post' failed due to: Deserializing '2020-06-05T11:42:38.585Z' to 'DateTime' failed due
to: type 'String' is not a subtype of type 'int' in type cast
how do I fix that?
You can import the Iso8601DateTimeSerializer directly from built_value - don't copy the file over to your project.
Your final serializers.dart should look like:
import 'package:built_value/iso_8601_date_time_serializer.dart';
import 'package:built_value/iso_8601_duration_serializer.dart';
import 'package:built_value/serializer.dart';
import 'package:built_value/standard_json_plugin.dart';
part 'serializers.g.dart';
#SerializersFor([
// your built value classes
])
final Serializers serializers = (_$serializers.toBuilder()
..add(Iso8601DateTimeSerializer())
..add(Iso8601DurationSerializer())
..addPlugin(StandardJsonPlugin())
).build();
You need to add a custom DateTime serializer that you can find here: Iso8601DateTimeSerializer
create a new dart file (I named it iso8601_date_time_serializer.dart)
paste the code from 1
add the import to your serializers.dart file (import 'iso8601_date_time_serializer.dart';)
edit your serializers.g.dart file
Serializers _$serializers = (new Serializers().toBuilder()
..add(Iso8601DateTimeSerializer())
..add(Post.serializer) // I assume you have this in yours
..addPlugin(StandardJsonPlugin()))
.build();
Please note that this modification might be deleted if you regenerate the code with build_runner.
In case you want to dig deeper, I got the answer from built_value GitHub issue 454

How to filter Query by nested join in Aqueduct 3?

I have models (simplify):
class _User {
int id;
#Relate(#users)
Currency currency;
}
class _Currency {
int id;
ManagedSet<Price> prices;
ManagedSet<User> users;
}
class _Price {
int id;
#Relate(#prices)
Currency currency;
ManagedSet<DefaultPrice> defaultPrices;
}
class _Game {
int id;
String code;
}
class _DefaultPrice {
int id;
#Relate(#defaultPrices)
Price price;
#Relate(#defaultPrices)
EventTemplate eventTemplate;
}
class _EventTemplate {
int id;
ManagedSet<DefaultPrice> defaultPrices;
#Relate(#eventTemplates)
Game game;
}
And now i want to fetch all event templates for a particular game with included default prices but only with a certain currency.
To solve it i use this code in my controller:
final String gameCode = request.path.variables['gameCode'];
final User user = request.attachments['user'];
final eventTemplatesQuery = Query<EventTemplate>(database)
..where((eventTemplate) => eventTemplate.game.code).equalTo(gameCode);
eventTemplatesQuery.join(set: (eventTemplate) => eventTemplate.defaultPrices)
..where((defaultPrice) => defaultPrice.price.currency.id).equalTo(user.currency.id);
// ..where((defaultPrice) => defaultPrice.price.currency).identifiedBy(user.currency.id); // the same result
final eventTemplates = await eventTemplatesQuery.fetch();
I expect that all event templates will be selected, filtered by the game code, after which default prices filtered by currency will be joined. But instead I get an error:
[FINE] aqueduct: Query (8ms) SELECT t0.id,t0.code,t0.description,t0.createdAt,t0.updatedAt,t0.game_id,t1.id,t1.createdAt,t1.updatedAt,t1.eventTemplate_id,t1.price_id FROM _EventTemplate t0 LEFT OUTER JOIN _DefaultPrice t1 ON (t0.id=t1.eventTemplate_id AND t3.id = #t1t3_id:int8) LEFT OUTER JOIN _Price t2 ON t1.price_id=t2.id LEFT OUTER JOIN _Currency t3 ON t2.currency_id=t3.id LEFT OUTER JOIN _Game t4 ON t0.game_id=t4.id WHERE t4.code LIKE #t0t4_code:text {t0t4_code: SM, t1t3_id: 8}
[WARNING] aqueduct: PostgreSQLSeverity.error 42P01: missing FROM-clause entry for table "t3"
[SEVERE] aqueduct: POST {{ request.toDebugString() }} PostgreSQLSeverity.error 42P01: missing FROM-clause entry for table "t3"
Looks like Aqueduct ORM can`t filter with nested JOINs But there is nothing in the documentation about limits or restrictions in this case.
Aqueduct CLI version: 3.1.0+1
Dart VM version: 2.1.0 (Tue Nov 13 18:22:02 2018 +0100) on "windows_x64"
postgres (PostgreSQL) 10.6 (Ubuntu 10.6-1.pgdg18.04+1)