Skip to content

Commit

Permalink
Merge pull request #6 from mbayopanda/official-bhima-stock
Browse files Browse the repository at this point in the history
Official bhima stock
  • Loading branch information
mbayopanda committed Jan 29, 2023
2 parents c337ddd + b0072c2 commit 27bd7ef
Show file tree
Hide file tree
Showing 17 changed files with 1,214 additions and 47 deletions.
2 changes: 1 addition & 1 deletion ios/Flutter/AppFrameworkInfo.plist
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>9.0</string>
<string>11.0</string>
</dict>
</plist>
2 changes: 1 addition & 1 deletion ios/Podfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'
# platform :ios, '11.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
Expand Down
4 changes: 2 additions & 2 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
connectivity_plus: 413a8857dd5d9f1c399a39130850d02fe0feaf7e
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
network_info_plus: b78876159360f5580608c2cea620d6ceffabd0ad
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904

PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3

COCOAPODS: 1.11.3
6 changes: 3 additions & 3 deletions ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
Expand Down Expand Up @@ -417,7 +417,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
Expand Down Expand Up @@ -466,7 +466,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
Expand Down
4 changes: 4 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import 'package:bhima_collect/screens/depot.dart';
import 'package:bhima_collect/screens/home.dart';
import 'package:bhima_collect/screens/settings.dart';
import 'package:bhima_collect/screens/stock_entry.dart';
import 'package:bhima_collect/screens/stock_entry_integration.dart';
import 'package:bhima_collect/screens/stock_exit.dart';
import 'package:bhima_collect/screens/stock_list.dart';
import 'package:bhima_collect/screens/stock_loss.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

Expand Down Expand Up @@ -52,6 +54,8 @@ class _MyAppState extends State<MyApp> {
'/stock': (context) => StockListPage(),
'/stock_entry': (context) => StockEntryPage(),
'/stock_exit': (context) => StockExitPage(),
'/stock_integration': (context) => const StockEntryIntegration(),
'/stock_loss': (context) => const StockLossPage(),
},
);
}
Expand Down
55 changes: 54 additions & 1 deletion lib/models/stock_movement.dart
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,33 @@ class StockMovement {
final db = await database;

// Get data from local movements and latest online data received
// String query = '''
// SELECT z.depot_uuid, z.inventory_text AS text, z.lot_label AS label,
// SUM(z.quantity) quantity,
// z.code, z.unit_type, z.isExit, z.inventory_uuid, z.lot_uuid,
// z.expiration_date, z.unit_cost
// FROM (
// SELECT
// i.uuid AS inventory_uuid, l.uuid AS lot_uuid,
// m.depotUuid AS depot_uuid, i.label AS inventory_text, l.label AS lot_label,
// SUM(IIF(m.isExit = 0, 1 * m.quantity, -1 * m.quantity)) quantity,
// m.isExit, i.code, i.unit AS unit_type, l.expiration_date, l.unit_cost
// FROM stock_movement m
// JOIN inventory_lot l ON l.uuid = m.lotUuid
// JOIN inventory i ON i.uuid = l.inventory_uuid
// WHERE m.isSync IS null OR m.isSync = 0
// GROUP BY m.depotUuid, l.inventory_uuid, l.uuid
// UNION ALL
// SELECT
// lot.inventory_uuid AS inventory_uuid, lot.uuid AS lot_uuid,
// lot.depot_uuid AS depot_uuid, lot.text AS inventory_text, lot.label AS lot_label, lot.quantity,
// 0 AS isExit, lot.code, lot.unit_type AS unit_type, lot.expiration_date, lot.unit_cost
// FROM lot
// GROUP BY lot.depot_uuid, lot.inventory_uuid, lot.uuid
// ) z
// GROUP BY z.depot_uuid, z.inventory_uuid, z.lot_uuid
// ORDER BY z.inventory_text, z.lot_label;
// ''';
String query = '''
SELECT z.depot_uuid, z.inventory_text AS text, z.lot_label AS label,
SUM(z.quantity) quantity,
Expand All @@ -215,7 +242,7 @@ class StockMovement {
SELECT
i.uuid AS inventory_uuid, l.uuid AS lot_uuid,
m.depotUuid AS depot_uuid, i.label AS inventory_text, l.label AS lot_label,
SUM(IIF(m.isExit = 0, 1 * m.quantity, -1 * m.quantity)) quantity,
SUM(CASE WHEN m.isExit = 0 THEN 1 * m.quantity ELSE -1 * m.quantity END) quantity,
m.isExit, i.code, i.unit AS unit_type, l.expiration_date, l.unit_cost
FROM stock_movement m
JOIN inventory_lot l ON l.uuid = m.lotUuid
Expand Down Expand Up @@ -325,4 +352,30 @@ class StockMovement {
where: 'uuid IS NOT NULL',
);
}

// get lots from local integrations
static Future<List> getLocalLots(dynamic database) async {
// Get a reference to the database.
final db = await database;

// Get data from local movements and latest online data received
String query = '''
SELECT
l.uuid,
l.label,
l.quantity,
l.unit_cost,
l.expiration_date,
l.inventory_uuid,
m.isSync,
m.movementUuid
FROM stock_movement m
JOIN lot l ON l.uuid = m.lotUuid
WHERE m.fluxId = 13 AND m.isExit = 0 AND (m.isSync IS NULL OR m.isSync = 0);
''';
final List<Map<String, dynamic>> maps = await db.rawQuery(query);

// Convert the List<Map<String, dynamic> into a List<StockMovement>.
return maps;
}
}
114 changes: 106 additions & 8 deletions lib/screens/home.dart
Original file line number Diff line number Diff line change
Expand Up @@ -142,16 +142,53 @@ class _HomePageState extends State<HomePage> {
.where((element) => element.isSync == 0 || element.isSync == null)
.toList();

var grouped = lots.groupListsBy((element) => element.movementUuid);
var groupedByIsExit = lots.groupListsBy((element) => element.isExit);

_maxToSync = grouped.length;
List<StockMovement> exitMovement = [];
List<StockMovement> entryMovement = [];

groupedByIsExit.forEach((key, value) {
if (key == 1) {
exitMovement = value;
} else {
entryMovement = value;
}
});

var entryGrouped =
entryMovement.groupListsBy((element) => element.movementUuid);

var exitGrouped =
exitMovement.groupListsBy((element) => element.movementUuid);

_maxToSync = entryGrouped.length + exitGrouped.length;
_countSynced = 0;
_progress = _maxToSync != 0 ? 0 : 100;
grouped.forEach((key, value) async {

// NOTE: Sync entries first before exits

entryGrouped.forEach((key, value) async {
var result =
await connexion.post(url, {'lots': value, 'sync_mobile': 1});

if (key != null && result != null && result['uuids'] != null) {
// update the sync status for valid lots of the movements
await StockMovement.updateSyncStatus(database, key, result['uuids']);
setState(() {
_countSynced++;
_progress = ((_countSynced / _maxToSync) * 100).round();
});
}
});

// fetch fresh data from the server after entries
await fetchLots();

exitGrouped.forEach((key, value) async {
var result =
await connexion.post(url, {'lots': value, 'sync_mobile': 1});

if (key != null && result != null) {
if (key != null && result != null && result['uuids'] != null) {
// update the sync status for valid lots of the movements
await StockMovement.updateSyncStatus(database, key, result['uuids']);
setState(() {
Expand All @@ -160,6 +197,23 @@ class _HomePageState extends State<HomePage> {
});
}
});

// fetch fresh data from the server after exits
await fetchLots();
} catch (e) {
print(e);
}
}

// sync local lots from integration
Future syncLots() async {
try {
const url = '/stock/lots/create';
List lots = await StockMovement.getLocalLots(database);
var grouped = lots.groupListsBy((element) => element['movementUuid']);
grouped.forEach((key, value) async {
await connexion.post(url, {'lots': value});
});
} catch (e) {
print(e);
}
Expand All @@ -178,12 +232,12 @@ class _HomePageState extends State<HomePage> {
// set the connection to the server
await serverConnection();

// send local lots
await syncLots();

// send local stock movements (not synced)
await syncStockMovements();

// fetch fresh data from the server
await fetchLots();

setState(() {
lastUpdate = DateTime.now();
_formattedLastUpdate = formatDate(
Expand All @@ -209,6 +263,11 @@ class _HomePageState extends State<HomePage> {
padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 20),
primary: Colors.green[700],
);
final ButtonStyle btnRedStyle = ElevatedButton.styleFrom(
textStyle: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 20),
primary: Colors.red[700],
);

return Scaffold(
appBar: AppBar(
Expand Down Expand Up @@ -285,7 +344,27 @@ class _HomePageState extends State<HomePage> {
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
Icon(Icons.add),
Text('Entrée de stock'),
Text('Réception'),
],
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/stock_integration')
.then((value) => Provider.of<EntryMovement>(
context,
listen: false)
.reset());
},
style: btnStyle,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
Icon(Icons.add),
Text('Integration de stock'),
],
),
),
Expand Down Expand Up @@ -345,6 +424,25 @@ class _HomePageState extends State<HomePage> {
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/stock_loss').then(
(value) => Provider.of<EntryMovement>(context,
listen: false)
.reset());
},
style: btnRedStyle,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
Icon(Icons.delete_outline),
Text('Perte de stock'),
],
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: _progress > 0
Expand Down
3 changes: 2 additions & 1 deletion lib/screens/settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ class _SettingsPageState extends State<SettingsPage> {
/**
* Include empty lots for having lots which are sent by not yet received
*/
const lotDataUrl = '/stock/lots/depots?includeEmptyLot=1';
const lotDataUrl = '/stock/lots/depots?includeEmptyLot=1&fullList=1';

List lotsRaw = await connexion.api(lotDataUrl);

List<Lot> lots = lotsRaw.map((lot) {
Expand Down
Loading

0 comments on commit 27bd7ef

Please sign in to comment.