
Introduces the ability to validate a stock reception by sending updated move line quantities to the backend. This includes: - Adding a new API call to update stock picking move lines. - Integrating a "Validate Reception" button within the quick actions component on the reception details page. - Implementing the logic to gather move line data and call the new API endpoint. - Enhancing error messages on the scan page for products not expected in the current reception. - Improving type safety for API response data.
374 lines
13 KiB
Dart
374 lines
13 KiB
Dart
import 'package:e_scan/backend/objectbox/entities/stock_picking/stock_picking_record_entity.dart';
|
|
import 'package:e_scan/backend/objectbox/objectbox_manager.dart';
|
|
import 'package:e_scan/backend/schema/auth/auth_model.dart';
|
|
import 'package:e_scan/backend/schema/stock_picking/stock_picking_model.dart';
|
|
import 'package:e_scan/backend/schema/stock_picking/stock_picking_record_model.dart';
|
|
import 'package:e_scan/backend/schema/stock_picking/update_move_line_dto.dart';
|
|
import 'package:e_scan/provider_container.dart';
|
|
import 'package:e_scan/services/dio_service.dart';
|
|
import 'package:e_scan/services/token_provider.dart';
|
|
import 'package:e_scan/utils/utils.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:multiple_result/multiple_result.dart';
|
|
|
|
class ApiCalls {
|
|
static DioService dioService = DioService(
|
|
tokenProvider: providerContainer.read(tokenProvider),
|
|
);
|
|
|
|
static Future<Result<AuthModel, Error>> signIn({
|
|
required String email,
|
|
required String password,
|
|
}) async {
|
|
try {
|
|
final response = await dioService.post(
|
|
path: '/simpos/v1/sign_in',
|
|
data: {
|
|
"params": {
|
|
"login": email,
|
|
"password": password,
|
|
"db": "bitnami_odoo",
|
|
},
|
|
},
|
|
);
|
|
if (response.statusCode == 200) {
|
|
final data = response.data;
|
|
if (data['result']['success'] == true) {
|
|
String? cookie;
|
|
if (response.headers.map.containsKey('set-cookie')) {
|
|
cookie = response.headers.map['set-cookie']?.firstOrNull;
|
|
}
|
|
final auth = AuthModel.fromJson(
|
|
data['result']['data'],
|
|
).copyWith(sessionId: cookie);
|
|
return Result.success(auth);
|
|
} else {
|
|
return Result.error(Error(data['result']['success']));
|
|
}
|
|
} else {
|
|
debugPrint('Erreur réseau: ${response.statusCode}');
|
|
return Result.error(Error(response.statusMessage));
|
|
}
|
|
} catch (e) {
|
|
debugPrint('Erreur lors de la requête: $e');
|
|
return Result.error(Error(e));
|
|
}
|
|
}
|
|
|
|
static Future<Result<List<StockPickingRecordEntity>, Error>>
|
|
getAllStockPiking() async {
|
|
try {
|
|
final stockPickingRecords = objectboxManager.store
|
|
.box<StockPickingRecordEntity>();
|
|
if (!(await checkInternetConnexion())) {
|
|
// return local data
|
|
return Result.success(stockPickingRecords.getAll());
|
|
}
|
|
final response = await dioService.post(
|
|
path: '/web/dataset/call_kw/stock.picking/web_search_read',
|
|
data: {
|
|
//"id": 23,
|
|
//"jsonrpc": "2.0",
|
|
//"method": "call",
|
|
"params": {
|
|
"model": "stock.picking",
|
|
"method": "web_search_read",
|
|
"args": [],
|
|
"kwargs": {
|
|
"specification": {
|
|
"company_id": {"fields": {}},
|
|
"priority": {},
|
|
"name": {},
|
|
"partner_id": {
|
|
"fields": {"display_name": {}},
|
|
},
|
|
"location_dest_id": {
|
|
"fields": {"complete_name": {}},
|
|
},
|
|
"location_id": {
|
|
"fields": {"complete_name": {}},
|
|
},
|
|
"user_id": {
|
|
"fields": {"display_name": {}},
|
|
},
|
|
"scheduled_date": {},
|
|
"picking_type_code": {},
|
|
"products_availability_state": {},
|
|
"products_availability": {},
|
|
"date_deadline": {},
|
|
"date_done": {},
|
|
"origin": {},
|
|
"backorder_id": {
|
|
"fields": {"display_name": {}},
|
|
},
|
|
"picking_type_id": {
|
|
"fields": {"display_name": {}},
|
|
},
|
|
"state": {},
|
|
"activity_exception_decoration": {},
|
|
"activity_exception_icon": {},
|
|
"json_popover": {},
|
|
"move_line_ids_without_package": {
|
|
"fields": {
|
|
"product_id": {
|
|
"fields": {"display_name": {}, "barcode": {}},
|
|
},
|
|
"quantity": {}, // quantité
|
|
},
|
|
},
|
|
"move_ids_without_package": {
|
|
"fields": {
|
|
"product_id": {
|
|
"fields": {"display_name": {}, "barcode": {}},
|
|
},
|
|
"quantity": {}, // quantité
|
|
"product_uom_qty": {}, //quantité demandé
|
|
},
|
|
"context": {
|
|
"form_view_ref": "stock.view_stock_move_operations",
|
|
},
|
|
"limit": 40,
|
|
"order": "",
|
|
},
|
|
},
|
|
"offset": 0,
|
|
"order": "",
|
|
"limit": 80,
|
|
"context": {
|
|
"lang": "en_US",
|
|
"tz": "Africa/Nairobi",
|
|
"uid": 2,
|
|
"allowed_company_ids": [1],
|
|
"bin_size": true,
|
|
"active_model": "stock.picking.type",
|
|
"active_id": 2,
|
|
"active_ids": [2],
|
|
"contact_display": "partner_address",
|
|
"default_picking_type_id": 2,
|
|
"default_company_id": 1,
|
|
"current_company_id": 1,
|
|
},
|
|
"count_limit": 10001,
|
|
"domain": [
|
|
["picking_type_code", "=", "incoming"],
|
|
],
|
|
},
|
|
},
|
|
},
|
|
);
|
|
if (response.statusCode == 200) {
|
|
final data = response.data as Map<String, dynamic>;
|
|
if (data.containsKey('result')) {
|
|
final result = StockPickingResponseModel.fromJson(data);
|
|
final recordsModel =
|
|
result.result?.records ?? <StockPickingRecordModel>[];
|
|
// add data to local
|
|
final records = recordsModel.map((e) => e.toEntity()).toList();
|
|
return Result.success(records);
|
|
} else {
|
|
return Result.error(Error(data['error']));
|
|
}
|
|
} else {
|
|
debugPrint('Erreur réseau: ${response.statusCode}');
|
|
return Result.error(Error(response.statusMessage));
|
|
}
|
|
} catch (e) {
|
|
debugPrint('Erreur lors de la requête: $e');
|
|
return Result.error(Error(e));
|
|
}
|
|
}
|
|
|
|
static Future<Result<StockPickingRecordEntity, Error>> getStockPikingById({
|
|
required int id,
|
|
}) async {
|
|
try {
|
|
final stockPickingRecords = objectboxManager.store
|
|
.box<StockPickingRecordEntity>();
|
|
if (!(await checkInternetConnexion())) {
|
|
// return local data
|
|
final entity = stockPickingRecords.get(id);
|
|
if (entity == null) return Result.error(Error('Not found'));
|
|
return Result.success(entity);
|
|
}
|
|
final response = await dioService.post(
|
|
path: '/web/dataset/call_kw/stock.picking/web_read',
|
|
data: {
|
|
"params": {
|
|
"model": "stock.picking",
|
|
"method": "web_read",
|
|
"args": [
|
|
[id],
|
|
],
|
|
"kwargs": {
|
|
"context": {
|
|
"lang": "en_US",
|
|
"tz": "Africa/Nairobi",
|
|
"uid": 2,
|
|
"allowed_company_ids": [1],
|
|
"bin_size": true,
|
|
"active_model": "stock.picking.type",
|
|
"active_id": 2,
|
|
"active_ids": [2],
|
|
"contact_display": "partner_address",
|
|
"default_picking_type_id": 2,
|
|
"default_company_id": 1,
|
|
},
|
|
"specification": {
|
|
"state": {},
|
|
"return_count": {},
|
|
"priority": {},
|
|
"picking_type_code": {},
|
|
"name": {},
|
|
"partner_id": {
|
|
"fields": {"display_name": {}},
|
|
},
|
|
"picking_type_id": {
|
|
"fields": {"display_name": {}},
|
|
},
|
|
"location_id": {
|
|
"fields": {"complete_name": {}},
|
|
},
|
|
"location_dest_id": {
|
|
"fields": {"complete_name": {}},
|
|
},
|
|
"backorder_id": {
|
|
"fields": {"display_name": {}},
|
|
},
|
|
"use_create_lots": {},
|
|
"scheduled_date": {},
|
|
"json_popover": {},
|
|
"date_deadline": {},
|
|
"products_availability_state": {},
|
|
"products_availability": {},
|
|
"date_done": {},
|
|
"origin": {},
|
|
"picking_properties": {},
|
|
"move_line_ids_without_package": {
|
|
"fields": {
|
|
"product_id": {
|
|
"fields": {"display_name": {}, "barcode": {}},
|
|
},
|
|
"quantity": {}, // quantité
|
|
},
|
|
},
|
|
"move_ids_without_package": {
|
|
"fields": {
|
|
"product_id": {
|
|
"fields": {"display_name": {}, "barcode": {}},
|
|
},
|
|
"quantity": {}, // quantité
|
|
"product_uom_qty": {}, //quantité demandé
|
|
},
|
|
"context": {
|
|
"form_view_ref": "stock.view_stock_move_operations",
|
|
},
|
|
"limit": 40,
|
|
"order": "",
|
|
},
|
|
"id": {},
|
|
"package_level_ids": {
|
|
"fields": {
|
|
"is_fresh_package": {},
|
|
"company_id": {"fields": {}},
|
|
"package_id": {
|
|
"fields": {"display_name": {}},
|
|
},
|
|
"state": {}, //done, ready, waiting,
|
|
"is_done": {},
|
|
},
|
|
"limit": 40,
|
|
"order": "",
|
|
},
|
|
"move_type": {},
|
|
"user_id": {
|
|
"fields": {"display_name": {}},
|
|
},
|
|
"sale_id": {
|
|
"fields": {"display_name": {}},
|
|
},
|
|
"note": {},
|
|
"show_check_availability": {},
|
|
"has_scrap_move": {},
|
|
"has_packages": {},
|
|
"is_locked": {},
|
|
"show_next_pickings": {},
|
|
"company_id": {"fields": {}},
|
|
"picking_type_entire_packs": {},
|
|
"display_name": {},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
);
|
|
if (response.statusCode == 200) {
|
|
final data = response.data as Map<String, dynamic>;
|
|
if (data.containsKey('result')) {
|
|
final datas = data['result'] as List;
|
|
if (datas.isNotEmpty) {
|
|
final recordModel = StockPickingRecordModel.fromJson(datas.first);
|
|
final entity = recordModel.toEntity();
|
|
return Result.success(entity);
|
|
} else {
|
|
return Result.error(Error('Data not found'));
|
|
}
|
|
} else {
|
|
return Result.error(Error(data['error']));
|
|
}
|
|
} else {
|
|
debugPrint('Erreur réseau: ${response.statusCode}');
|
|
return Result.error(Error(response.statusMessage));
|
|
}
|
|
} catch (e) {
|
|
debugPrint('Erreur lors de la requête: $e');
|
|
return Result.error(Error(e));
|
|
}
|
|
}
|
|
|
|
static Future<bool> updateAllMoveLineOnStockPiking({
|
|
required int stockPickingId,
|
|
required List<UpdateMoveLineDto> moveLineDto,
|
|
}) async {
|
|
try {
|
|
final response = await dioService.post(
|
|
path: '/web/dataset/call_kw/stock.picking/write',
|
|
data: {
|
|
"jsonrpc": "2.0",
|
|
"method": "call",
|
|
"params": {
|
|
"model": "stock.picking",
|
|
"method": "write",
|
|
"args": [
|
|
[
|
|
stockPickingId, //id stock piking
|
|
],
|
|
{
|
|
"move_line_ids": [...moveLineDto.map((e) => e.toList())],
|
|
},
|
|
],
|
|
"kwargs": {"context": {}},
|
|
},
|
|
},
|
|
);
|
|
if (response.statusCode == 200) {
|
|
final data = response.data as Map<String, dynamic>;
|
|
if (data.containsKey('result')) {
|
|
final datas = data['result'] as List;
|
|
if (datas.isNotEmpty) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
debugPrint('Erreur réseau: ${response.statusCode}');
|
|
return false;
|
|
}
|
|
} catch (e) {
|
|
debugPrint('Erreur lors de la requête: $e');
|
|
return false;
|
|
}
|
|
}
|
|
}
|