Distinguish expiry/best before dates (closes #851)

This commit is contained in:
Bernd Bestel
2020-11-15 19:53:44 +01:00
parent 1d50d5dd22
commit b393998601
39 changed files with 348 additions and 192 deletions

View File

@@ -13,7 +13,7 @@ class CalendarService extends BaseService
if (GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING)
{
$products = $this->getDatabase()->products();
$titlePrefix = $this->getLocalizationService()->__t('Product expires') . ': ';
$titlePrefix = $this->getLocalizationService()->__t('Product due') . ': ';
foreach ($this->getStockService()->GetCurrentStock() as $currentStockEntry)
{

View File

@@ -85,7 +85,7 @@ class DemoDataGeneratorService extends BaseService
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id) VALUES ('{$this->__t_sql('Sieved tomatoes')}', 5, 5, 5, 1, 3); --17
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id) VALUES ('{$this->__t_sql('Salami')}', 2, 3, 3, 1, 6); --18
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id) VALUES ('{$this->__t_sql('Toast')}', 3, 5, 5, 1, 2); --19
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id, default_best_before_days_after_freezing, default_best_before_days_after_thawing) VALUES ('{$this->__t_sql('Minced meat')}', 2, 3, 3, 1, 4, 180, 2); --20
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id, default_best_before_days_after_freezing, default_best_before_days_after_thawing, due_type) VALUES ('{$this->__t_sql('Minced meat')}', 2, 3, 3, 1, 4, 180, 2, 2); --20
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id, enable_tare_weight_handling, tare_weight, calories) VALUES ('{$this->__t_sql('Flour')}', 3, 8, 8, 1, 3, 1, 500, 2); --21
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id, calories) VALUES ('{$this->__t_sql('Sugar')}', 3, 3, 3, 1, 3, 4); --22
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id, calories) VALUES ('{$this->__t_sql('Milk')}', 2, 10, 10, 1, 6, 1); --23
@@ -250,6 +250,7 @@ class DemoDataGeneratorService extends BaseService
$stockService->AddProduct(15, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-30 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(15, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(15, 1, date('Y-m-d', strtotime('-2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(20, 1, date('Y-m-d', strtotime('-1 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(21, 1500, date('Y-m-d', strtotime('+200 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(21, 2500, date('Y-m-d', strtotime('+200 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);
$stockService->AddProduct(22, 1, date('Y-m-d', strtotime('+200 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice(), null, $this->NextSupermarketId(), $stockTransactionId);

View File

@@ -52,25 +52,24 @@ class StockService extends BaseService
}
}
public function AddExpiredProductsToShoppingList($listId = 1)
public function AddOverdueProductsToShoppingList($listId = 1)
{
if (!$this->ShoppingListExists($listId))
{
throw new \Exception('Shopping list does not exist');
}
$expiredProducts = $this->GetExpiringProducts(-1);
$overdueProducts = $this->GetDueProducts(-1);
foreach ($expiredProducts as $expiredProduct)
foreach ($overdueProducts as $overdueProduct)
{
$product = $this->getDatabase()->products()->where('id', $expiredProduct->product_id)->fetch();
$alreadyExistingEntry = $this->getDatabase()->shopping_list()->where('product_id', $expiredProduct->product_id)->fetch();
$product = $this->getDatabase()->products()->where('id', $overdueProduct->product_id)->fetch();
$alreadyExistingEntry = $this->getDatabase()->shopping_list()->where('product_id', $overdueProduct->product_id)->fetch();
if (!$alreadyExistingEntry)
{
$shoppinglistRow = $this->getDatabase()->shopping_list()->createRow([
'product_id' => $expiredProduct->product_id,
'product_id' => $overdueProduct->product_id,
'amount' => 1,
'shopping_list_id' => $listId
]);
@@ -101,7 +100,7 @@ class StockService extends BaseService
$amount = $amount - floatval($productDetails->stock_amount) - floatval($productDetails->product->tare_weight);
}
//Sets the default best before date, if none is supplied
//Set the default due date, if none is supplied
if ($bestBeforeDate == null)
{
if (intval($productDetails->product->default_best_before_days) == -1)
@@ -479,12 +478,13 @@ class StockService extends BaseService
}
}
public function GetExpiringProducts(int $days = 5, bool $excludeExpired = false)
public function GetDueProducts(int $days = 5, bool $excludeOverdue = false)
{
$currentStock = $this->GetCurrentStock(false);
$currentStock = FindAllObjectsInArrayByPropertyValue($currentStock, 'best_before_date', date('Y-m-d 23:59:59', strtotime("+$days days")), '<');
$currentStock = FindAllObjectsInArrayByPropertyValue($currentStock, 'due_type', 1);
if ($excludeExpired)
if ($excludeOverdue)
{
$currentStock = FindAllObjectsInArrayByPropertyValue($currentStock, 'best_before_date', date('Y-m-d 23:59:59', strtotime('-1 days')), '>');
}
@@ -492,6 +492,15 @@ class StockService extends BaseService
return $currentStock;
}
public function GetExpiredProducts()
{
$currentStock = $this->GetCurrentStock(false);
$currentStock = FindAllObjectsInArrayByPropertyValue($currentStock, 'best_before_date', date('Y-m-d 23:59:59', strtotime("-1 days")), '<');
$currentStock = FindAllObjectsInArrayByPropertyValue($currentStock, 'due_type', 2);
return $currentStock;
}
public function GetMissingProducts()
{
$sql = 'SELECT * FROM stock_missing_products_including_opened';
@@ -550,7 +559,7 @@ class StockService extends BaseService
$product = $this->getDatabase()->products($productId);
$productBarcodes = $this->getDatabase()->product_barcodes()->where('product_id', $productId)->fetchAll();
$productLastUsed = $this->getDatabase()->stock_log()->where('product_id', $productId)->where('transaction_type', self::TRANSACTION_TYPE_CONSUME)->where('undone', 0)->max('used_date');
$nextBestBeforeDate = $this->getDatabase()->stock()->where('product_id', $productId)->min('best_before_date');
$nextDueDate = $this->getDatabase()->stock()->where('product_id', $productId)->min('best_before_date');
$quPurchase = $this->getDatabase()->quantity_units($product->qu_id_purchase);
$quStock = $this->getDatabase()->quantity_units($product->qu_id_stock);
$location = $this->getDatabase()->locations($product->location_id);
@@ -584,7 +593,7 @@ class StockService extends BaseService
'oldest_price' => $oldestPrice,
'last_shopping_location_id' => $lastShoppingLocation,
'default_shopping_location_id' => $product->shopping_location_id,
'next_best_before_date' => $nextBestBeforeDate,
'next_due_date' => $nextDueDate,
'location' => $location,
'average_shelf_life_days' => $averageShelfLifeDays,
'spoil_rate_percent' => $spoilRate,
@@ -630,7 +639,7 @@ class StockService extends BaseService
public function GetProductStockEntries($productId, $excludeOpened = false, $allowSubproductSubstitution = false, $ordered = true)
{
// In order of next use:
// First expiring first, then first in first out
// First due first, then first in first out
$sqlWhereProductId = 'product_id = :1';