printer receipt

This commit is contained in:
efrilm
2025-11-04 22:13:15 +07:00
parent a87b62ca9f
commit 1b24bae23a
32 changed files with 4177 additions and 75 deletions
@@ -0,0 +1,142 @@
import 'dart:developer';
import 'package:dartz/dartz.dart';
import 'package:data_channel/data_channel.dart';
import 'package:injectable/injectable.dart';
import 'package:sqflite/sql.dart';
import '../../../common/database/database_helper.dart';
import '../../../domain/printer/printer.dart';
import '../printer_dtos.dart';
@injectable
class PrinterLocalDataProvider {
final DatabaseHelper _databaseHelper;
final _logName = 'PrinterLocalDataProvider';
PrinterLocalDataProvider(this._databaseHelper);
Future<DC<PrinterFailure, Unit>> createPrinter(PrinterDto printer) async {
final db = await _databaseHelper.database;
try {
log('Creating printer: ${printer.toString()}', name: _logName);
final printerExist = await findPrinterByCode(printer.code);
if (printerExist.hasData) {
return DC.error(
PrinterFailure.dynamicErrorMessage('Printer Telah Terdaftar'),
);
}
await db.insert(
'printers',
printer.toMapCreating(),
conflictAlgorithm: ConflictAlgorithm.abort,
);
log('Success created printer', name: _logName);
return DC.data(unit);
} catch (e) {
log('Error creating printer', name: _logName, error: e);
return DC.error(
PrinterFailure.dynamicErrorMessage('Error creating printer'),
);
}
}
Future<DC<PrinterFailure, Unit>> updatePrinter(
PrinterDto printer,
int id,
) async {
final db = await _databaseHelper.database;
try {
log('Updating printer: ${printer.toString()}', name: _logName);
final updatedRows = await db.update(
'printers',
printer.toMapForUpdate(),
where: 'id = ?',
whereArgs: [id],
);
if (updatedRows == 0) {
return DC.error(
PrinterFailure.dynamicErrorMessage('Printer not found'),
);
}
log('Success updated printer', name: _logName);
return DC.data(unit);
} catch (e) {
log('Error updating printer', name: _logName, error: e);
return DC.error(
PrinterFailure.dynamicErrorMessage('Error updating printer'),
);
}
}
Future<DC<PrinterFailure, Unit>> deletePrinter(int id) async {
final db = await _databaseHelper.database;
try {
log('Updatinf printer: ${id.toString()}', name: _logName);
final deletedRows = await db.delete(
'printers',
where: 'id = ?',
whereArgs: [id],
);
if (deletedRows == 0) {
return DC.error(
PrinterFailure.dynamicErrorMessage('Printer not found'),
);
}
log('Success deleted printer', name: _logName);
return DC.data(unit);
} catch (e) {
log('Error deleting printer', name: _logName, error: e);
return DC.error(
PrinterFailure.dynamicErrorMessage('Error deleting printer'),
);
}
}
Future<DC<PrinterFailure, PrinterDto>> findPrinterByCode(String code) async {
final db = await _databaseHelper.database;
try {
log('Getting printer by code: $code', name: _logName);
final result = await db.query(
'printers',
where: 'code = ?',
whereArgs: [code],
);
if (result.isEmpty) {
log('Printer with code $code not found');
return DC.error(
PrinterFailure.dynamicErrorMessage('Printer not found'),
);
}
final printer = PrinterDto.fromJson(result.first);
return DC.data(printer);
} catch (e) {
log('findPrinterByCode', name: _logName, error: e);
return DC.error(
PrinterFailure.dynamicErrorMessage('Error getting printer'),
);
}
}
}
@@ -0,0 +1,68 @@
part of '../printer_dtos.dart';
@freezed
class PrinterDto with _$PrinterDto {
const PrinterDto._();
const factory PrinterDto({
@JsonKey(name: 'id') required int id,
@JsonKey(name: 'code') required String code,
@JsonKey(name: 'name') required String name,
@JsonKey(name: 'address') required String address,
@JsonKey(name: 'paper') required String paper,
@JsonKey(name: 'type') required String type,
@JsonKey(name: 'created_at') required DateTime createdAt,
@JsonKey(name: 'updated_at') required DateTime updatedAt,
}) = _PrinterDto;
factory PrinterDto.fromJson(Map<String, dynamic> json) =>
_$PrinterDtoFromJson(json);
// Optional mapper to domain
Printer toDomain() => Printer(
id: id,
code: code,
name: name,
address: address,
paper: paper,
type: type,
createdAt: createdAt,
updatedAt: updatedAt,
);
factory PrinterDto.fromDomain(Printer printer) => PrinterDto(
id: printer.id,
code: printer.code,
name: printer.name,
address: printer.address,
paper: printer.paper,
type: printer.type,
createdAt: printer.createdAt,
updatedAt: printer.updatedAt,
);
Map<String, dynamic> toMapCreating() {
final now = DateTime.now().toIso8601String();
return {
'id': generateRandomNumber(),
'code': code,
'name': name,
'address': address,
'paper': paper,
'type': type,
'created_at': now,
'updated_at': now,
};
}
Map<String, dynamic> toMapForUpdate() {
return {
'code': code,
'name': name,
'address': address,
'paper': paper,
'type': type,
'updated_at': DateTime.now().toIso8601String(),
};
}
}
@@ -0,0 +1,9 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import '../../common/function/app_function.dart';
import '../../domain/printer/printer.dart';
part 'printer_dtos.freezed.dart';
part 'printer_dtos.g.dart';
part 'dtos/printer_dto.dart';
@@ -0,0 +1,356 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'printer_dtos.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models',
);
PrinterDto _$PrinterDtoFromJson(Map<String, dynamic> json) {
return _PrinterDto.fromJson(json);
}
/// @nodoc
mixin _$PrinterDto {
@JsonKey(name: 'id')
int get id => throw _privateConstructorUsedError;
@JsonKey(name: 'code')
String get code => throw _privateConstructorUsedError;
@JsonKey(name: 'name')
String get name => throw _privateConstructorUsedError;
@JsonKey(name: 'address')
String get address => throw _privateConstructorUsedError;
@JsonKey(name: 'paper')
String get paper => throw _privateConstructorUsedError;
@JsonKey(name: 'type')
String get type => throw _privateConstructorUsedError;
@JsonKey(name: 'created_at')
DateTime get createdAt => throw _privateConstructorUsedError;
@JsonKey(name: 'updated_at')
DateTime get updatedAt => throw _privateConstructorUsedError;
/// Serializes this PrinterDto to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of PrinterDto
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$PrinterDtoCopyWith<PrinterDto> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $PrinterDtoCopyWith<$Res> {
factory $PrinterDtoCopyWith(
PrinterDto value,
$Res Function(PrinterDto) then,
) = _$PrinterDtoCopyWithImpl<$Res, PrinterDto>;
@useResult
$Res call({
@JsonKey(name: 'id') int id,
@JsonKey(name: 'code') String code,
@JsonKey(name: 'name') String name,
@JsonKey(name: 'address') String address,
@JsonKey(name: 'paper') String paper,
@JsonKey(name: 'type') String type,
@JsonKey(name: 'created_at') DateTime createdAt,
@JsonKey(name: 'updated_at') DateTime updatedAt,
});
}
/// @nodoc
class _$PrinterDtoCopyWithImpl<$Res, $Val extends PrinterDto>
implements $PrinterDtoCopyWith<$Res> {
_$PrinterDtoCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of PrinterDto
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? code = null,
Object? name = null,
Object? address = null,
Object? paper = null,
Object? type = null,
Object? createdAt = null,
Object? updatedAt = null,
}) {
return _then(
_value.copyWith(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
code: null == code
? _value.code
: code // ignore: cast_nullable_to_non_nullable
as String,
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
address: null == address
? _value.address
: address // ignore: cast_nullable_to_non_nullable
as String,
paper: null == paper
? _value.paper
: paper // ignore: cast_nullable_to_non_nullable
as String,
type: null == type
? _value.type
: type // ignore: cast_nullable_to_non_nullable
as String,
createdAt: null == createdAt
? _value.createdAt
: createdAt // ignore: cast_nullable_to_non_nullable
as DateTime,
updatedAt: null == updatedAt
? _value.updatedAt
: updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime,
)
as $Val,
);
}
}
/// @nodoc
abstract class _$$PrinterDtoImplCopyWith<$Res>
implements $PrinterDtoCopyWith<$Res> {
factory _$$PrinterDtoImplCopyWith(
_$PrinterDtoImpl value,
$Res Function(_$PrinterDtoImpl) then,
) = __$$PrinterDtoImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({
@JsonKey(name: 'id') int id,
@JsonKey(name: 'code') String code,
@JsonKey(name: 'name') String name,
@JsonKey(name: 'address') String address,
@JsonKey(name: 'paper') String paper,
@JsonKey(name: 'type') String type,
@JsonKey(name: 'created_at') DateTime createdAt,
@JsonKey(name: 'updated_at') DateTime updatedAt,
});
}
/// @nodoc
class __$$PrinterDtoImplCopyWithImpl<$Res>
extends _$PrinterDtoCopyWithImpl<$Res, _$PrinterDtoImpl>
implements _$$PrinterDtoImplCopyWith<$Res> {
__$$PrinterDtoImplCopyWithImpl(
_$PrinterDtoImpl _value,
$Res Function(_$PrinterDtoImpl) _then,
) : super(_value, _then);
/// Create a copy of PrinterDto
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? code = null,
Object? name = null,
Object? address = null,
Object? paper = null,
Object? type = null,
Object? createdAt = null,
Object? updatedAt = null,
}) {
return _then(
_$PrinterDtoImpl(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
code: null == code
? _value.code
: code // ignore: cast_nullable_to_non_nullable
as String,
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
address: null == address
? _value.address
: address // ignore: cast_nullable_to_non_nullable
as String,
paper: null == paper
? _value.paper
: paper // ignore: cast_nullable_to_non_nullable
as String,
type: null == type
? _value.type
: type // ignore: cast_nullable_to_non_nullable
as String,
createdAt: null == createdAt
? _value.createdAt
: createdAt // ignore: cast_nullable_to_non_nullable
as DateTime,
updatedAt: null == updatedAt
? _value.updatedAt
: updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime,
),
);
}
}
/// @nodoc
@JsonSerializable()
class _$PrinterDtoImpl extends _PrinterDto {
const _$PrinterDtoImpl({
@JsonKey(name: 'id') required this.id,
@JsonKey(name: 'code') required this.code,
@JsonKey(name: 'name') required this.name,
@JsonKey(name: 'address') required this.address,
@JsonKey(name: 'paper') required this.paper,
@JsonKey(name: 'type') required this.type,
@JsonKey(name: 'created_at') required this.createdAt,
@JsonKey(name: 'updated_at') required this.updatedAt,
}) : super._();
factory _$PrinterDtoImpl.fromJson(Map<String, dynamic> json) =>
_$$PrinterDtoImplFromJson(json);
@override
@JsonKey(name: 'id')
final int id;
@override
@JsonKey(name: 'code')
final String code;
@override
@JsonKey(name: 'name')
final String name;
@override
@JsonKey(name: 'address')
final String address;
@override
@JsonKey(name: 'paper')
final String paper;
@override
@JsonKey(name: 'type')
final String type;
@override
@JsonKey(name: 'created_at')
final DateTime createdAt;
@override
@JsonKey(name: 'updated_at')
final DateTime updatedAt;
@override
String toString() {
return 'PrinterDto(id: $id, code: $code, name: $name, address: $address, paper: $paper, type: $type, createdAt: $createdAt, updatedAt: $updatedAt)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$PrinterDtoImpl &&
(identical(other.id, id) || other.id == id) &&
(identical(other.code, code) || other.code == code) &&
(identical(other.name, name) || other.name == name) &&
(identical(other.address, address) || other.address == address) &&
(identical(other.paper, paper) || other.paper == paper) &&
(identical(other.type, type) || other.type == type) &&
(identical(other.createdAt, createdAt) ||
other.createdAt == createdAt) &&
(identical(other.updatedAt, updatedAt) ||
other.updatedAt == updatedAt));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(
runtimeType,
id,
code,
name,
address,
paper,
type,
createdAt,
updatedAt,
);
/// Create a copy of PrinterDto
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$PrinterDtoImplCopyWith<_$PrinterDtoImpl> get copyWith =>
__$$PrinterDtoImplCopyWithImpl<_$PrinterDtoImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$PrinterDtoImplToJson(this);
}
}
abstract class _PrinterDto extends PrinterDto {
const factory _PrinterDto({
@JsonKey(name: 'id') required final int id,
@JsonKey(name: 'code') required final String code,
@JsonKey(name: 'name') required final String name,
@JsonKey(name: 'address') required final String address,
@JsonKey(name: 'paper') required final String paper,
@JsonKey(name: 'type') required final String type,
@JsonKey(name: 'created_at') required final DateTime createdAt,
@JsonKey(name: 'updated_at') required final DateTime updatedAt,
}) = _$PrinterDtoImpl;
const _PrinterDto._() : super._();
factory _PrinterDto.fromJson(Map<String, dynamic> json) =
_$PrinterDtoImpl.fromJson;
@override
@JsonKey(name: 'id')
int get id;
@override
@JsonKey(name: 'code')
String get code;
@override
@JsonKey(name: 'name')
String get name;
@override
@JsonKey(name: 'address')
String get address;
@override
@JsonKey(name: 'paper')
String get paper;
@override
@JsonKey(name: 'type')
String get type;
@override
@JsonKey(name: 'created_at')
DateTime get createdAt;
@override
@JsonKey(name: 'updated_at')
DateTime get updatedAt;
/// Create a copy of PrinterDto
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$PrinterDtoImplCopyWith<_$PrinterDtoImpl> get copyWith =>
throw _privateConstructorUsedError;
}
@@ -0,0 +1,31 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'printer_dtos.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$PrinterDtoImpl _$$PrinterDtoImplFromJson(Map<String, dynamic> json) =>
_$PrinterDtoImpl(
id: (json['id'] as num).toInt(),
code: json['code'] as String,
name: json['name'] as String,
address: json['address'] as String,
paper: json['paper'] as String,
type: json['type'] as String,
createdAt: DateTime.parse(json['created_at'] as String),
updatedAt: DateTime.parse(json['updated_at'] as String),
);
Map<String, dynamic> _$$PrinterDtoImplToJson(_$PrinterDtoImpl instance) =>
<String, dynamic>{
'id': instance.id,
'code': instance.code,
'name': instance.name,
'address': instance.address,
'paper': instance.paper,
'type': instance.type,
'created_at': instance.createdAt.toIso8601String(),
'updated_at': instance.updatedAt.toIso8601String(),
};
@@ -6,11 +6,14 @@ import 'package:injectable/injectable.dart';
import 'package:print_bluetooth_thermal/print_bluetooth_thermal.dart';
import '../../../domain/printer/printer.dart';
import '../datasource/local_data_provider.dart';
import '../printer_dtos.dart';
@Injectable(as: IPrinterRepository)
class PrinterRepository implements IPrinterRepository {
final PrinterLocalDataProvider _localDataProvider;
final _logName = 'PrinterRepository';
PrinterRepository();
PrinterRepository(this._localDataProvider);
@override
Future<Either<PrinterFailure, bool>> connectBluetooth(
@@ -117,4 +120,78 @@ class PrinterRepository implements IPrinterRepository {
);
}
}
@override
Future<Either<PrinterFailure, Unit>> createPrinter(Printer printer) async {
try {
final result = await _localDataProvider.createPrinter(
PrinterDto.fromDomain(printer),
);
if (result.hasError) {
return left(result.error!);
}
return right(unit);
} catch (e) {
log('createPrinterError', name: _logName, error: e);
return left(const PrinterFailure.unexpectedError());
}
}
@override
Future<Either<PrinterFailure, Unit>> deletePrinter(int id) async {
try {
final result = await _localDataProvider.deletePrinter(id);
if (result.hasError) {
return left(result.error!);
}
return right(unit);
} catch (e) {
log('deletePrinterError', name: _logName, error: e);
return left(const PrinterFailure.unexpectedError());
}
}
@override
Future<Either<PrinterFailure, Printer>> getPrinterByCode(String code) async {
try {
final result = await _localDataProvider.findPrinterByCode(code);
if (result.hasError) {
return left(result.error!);
}
final printer = result.data!.toDomain();
return right(printer);
} catch (e) {
log('getPrinterByCodeError', name: _logName, error: e);
return left(const PrinterFailure.unexpectedError());
}
}
@override
Future<Either<PrinterFailure, Unit>> updatePrinter(
Printer printer,
int id,
) async {
try {
final result = await _localDataProvider.updatePrinter(
PrinterDto.fromDomain(printer),
id,
);
if (result.hasError) {
return left(result.error!);
}
return right(unit);
} catch (e) {
log('updatePrinterError', name: _logName, error: e);
return left(const PrinterFailure.unexpectedError());
}
}
}