barcode_scanner/lib/backend/api/api_calls.dart
mandreshope 1d331acc54 feat: Streamlines product data and stock picking API
Refactors the product data model to primarily store `id`, `barcode`, and `displayName`. This simplifies the product structure, focusing on essential attributes for inventory and scanning operations.

Optimizes API calls for stock picking to fetch more relevant product details. Unnecessary fields are removed, and specific product attributes like `barcode` and `quantity` are now explicitly requested for stock moves.

Moves `StockPickingRecordModel` to its own dedicated file for improved code organization and maintainability. Updates all affected UI components and scanner logic to align with the revised product model.
2025-07-30 12:47:08 +03:00

317 lines
10 KiB
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/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:dio/dio.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<Map<String, dynamic>?> fetchProduct(String barcode) async {
final Dio dio = Dio(
BaseOptions(baseUrl: 'https://world.openfoodfacts.org'),
);
try {
final response = await dio.get('/api/v0/product/$barcode.json');
if (response.statusCode == 200) {
final data = response.data;
if (data['status'] == 1) {
return data['product'];
} else {
debugPrint('Produit non trouvé');
return null;
}
} else {
debugPrint('Erreur réseau: ${response.statusCode}');
return null;
}
} catch (e) {
debugPrint('Erreur lors de la requête: $e');
return null;
}
}
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<StockPickingResponseModel, Error>>
getAllStockPiking() async {
try {
if (!(await checkInternetConnexion())) {
// return local data
}
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": {},
},
"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_id", "=", 2],
],
},
},
},
);
if (response.statusCode == 200) {
final data = response.data;
if (data.containsKey('result')) {
return Result.success(StockPickingResponseModel.fromJson(data));
} 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<StockPickingRecordModel, Error>> getStockPikingById({
required int id,
}) async {
try {
if (!(await checkInternetConnexion())) {
// return local data
}
final response = await dioService.post(
path: '/web/dataset/call_kw/stock.picking/web_read',
data: {
"jsonrpc": "2.0",
"method": "call",
"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;
if (data.containsKey('result')) {
final datas = data['result'] as List;
if (datas.isNotEmpty) {
return Result.success(
StockPickingRecordModel.fromJson(datas.first),
);
} 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));
}
}
}