mirror of
https://github.com/grocy/grocy.git
synced 2025-09-19 02:57:44 +00:00
Compare commits
32 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
f4534a4bfb | ||
|
89553b7fa0 | ||
|
364f6b2051 | ||
|
fe83e2fa6f | ||
|
1f3dd58ddf | ||
|
da98efa833 | ||
|
3e6cf545d7 | ||
|
1080c3486c | ||
|
cd7b6b686d | ||
|
b84e6da0dd | ||
|
fc3a4c6899 | ||
|
12a2cb0bdf | ||
|
57a0864465 | ||
|
b3da837ede | ||
|
3de3e03ab3 | ||
|
78865a9d3c | ||
|
5b3230d63d | ||
|
04c93d937e | ||
|
5318e79f55 | ||
|
7bf4421d44 | ||
|
366152c049 | ||
|
70c00e81d9 | ||
|
f13abf483e | ||
|
0e723a0a9b | ||
|
4a35477c35 | ||
|
df7d360516 | ||
|
03eaa6c79f | ||
|
132999ce36 | ||
|
188407e3c7 | ||
|
8cf68ade30 | ||
|
d62657c698 | ||
|
3262e534dc |
61
composer.lock
generated
61
composer.lock
generated
@@ -159,20 +159,21 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "illuminate/container",
|
"name": "illuminate/container",
|
||||||
"version": "v5.7.8",
|
"version": "v5.7.11",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/illuminate/container.git",
|
"url": "https://github.com/illuminate/container.git",
|
||||||
"reference": "2582a994f2f8a153a4880de757a89ad4eeb083d7"
|
"reference": "4c90c3d3ba88e52da152e885d24c9f891a2ec545"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/illuminate/container/zipball/2582a994f2f8a153a4880de757a89ad4eeb083d7",
|
"url": "https://api.github.com/repos/illuminate/container/zipball/4c90c3d3ba88e52da152e885d24c9f891a2ec545",
|
||||||
"reference": "2582a994f2f8a153a4880de757a89ad4eeb083d7",
|
"reference": "4c90c3d3ba88e52da152e885d24c9f891a2ec545",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"illuminate/contracts": "5.7.*",
|
"illuminate/contracts": "5.7.*",
|
||||||
|
"illuminate/support": "5.7.*",
|
||||||
"php": "^7.1.3",
|
"php": "^7.1.3",
|
||||||
"psr/container": "^1.0"
|
"psr/container": "^1.0"
|
||||||
},
|
},
|
||||||
@@ -199,20 +200,20 @@
|
|||||||
],
|
],
|
||||||
"description": "The Illuminate Container package.",
|
"description": "The Illuminate Container package.",
|
||||||
"homepage": "https://laravel.com",
|
"homepage": "https://laravel.com",
|
||||||
"time": "2018-10-03T15:20:19+00:00"
|
"time": "2018-10-18T03:39:45+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "illuminate/contracts",
|
"name": "illuminate/contracts",
|
||||||
"version": "v5.7.8",
|
"version": "v5.7.11",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/illuminate/contracts.git",
|
"url": "https://github.com/illuminate/contracts.git",
|
||||||
"reference": "9532d673de305b0c0028c0ce60c8952b807d7bc3"
|
"reference": "64df81d3382d876f1c1d3d5481d89c93b61b8279"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/illuminate/contracts/zipball/9532d673de305b0c0028c0ce60c8952b807d7bc3",
|
"url": "https://api.github.com/repos/illuminate/contracts/zipball/64df81d3382d876f1c1d3d5481d89c93b61b8279",
|
||||||
"reference": "9532d673de305b0c0028c0ce60c8952b807d7bc3",
|
"reference": "64df81d3382d876f1c1d3d5481d89c93b61b8279",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -243,20 +244,20 @@
|
|||||||
],
|
],
|
||||||
"description": "The Illuminate Contracts package.",
|
"description": "The Illuminate Contracts package.",
|
||||||
"homepage": "https://laravel.com",
|
"homepage": "https://laravel.com",
|
||||||
"time": "2018-10-03T14:04:39+00:00"
|
"time": "2018-10-08T13:34:14+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "illuminate/events",
|
"name": "illuminate/events",
|
||||||
"version": "v5.7.8",
|
"version": "v5.7.11",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/illuminate/events.git",
|
"url": "https://github.com/illuminate/events.git",
|
||||||
"reference": "4cf622acc05592f86d4a5c77ad1a544d38e58dee"
|
"reference": "a8e5e3d601ad7f3571428176a578ddf03ce649d8"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/illuminate/events/zipball/4cf622acc05592f86d4a5c77ad1a544d38e58dee",
|
"url": "https://api.github.com/repos/illuminate/events/zipball/a8e5e3d601ad7f3571428176a578ddf03ce649d8",
|
||||||
"reference": "4cf622acc05592f86d4a5c77ad1a544d38e58dee",
|
"reference": "a8e5e3d601ad7f3571428176a578ddf03ce649d8",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -288,20 +289,20 @@
|
|||||||
],
|
],
|
||||||
"description": "The Illuminate Events package.",
|
"description": "The Illuminate Events package.",
|
||||||
"homepage": "https://laravel.com",
|
"homepage": "https://laravel.com",
|
||||||
"time": "2018-07-26T15:27:42+00:00"
|
"time": "2018-10-06T18:48:42+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "illuminate/filesystem",
|
"name": "illuminate/filesystem",
|
||||||
"version": "v5.7.8",
|
"version": "v5.7.11",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/illuminate/filesystem.git",
|
"url": "https://github.com/illuminate/filesystem.git",
|
||||||
"reference": "a09fae4470494dc9867609221b46fe844f2f3b70"
|
"reference": "cbb5650be36d7370f7ae5f039d2143952fa58f51"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/illuminate/filesystem/zipball/a09fae4470494dc9867609221b46fe844f2f3b70",
|
"url": "https://api.github.com/repos/illuminate/filesystem/zipball/cbb5650be36d7370f7ae5f039d2143952fa58f51",
|
||||||
"reference": "a09fae4470494dc9867609221b46fe844f2f3b70",
|
"reference": "cbb5650be36d7370f7ae5f039d2143952fa58f51",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -340,20 +341,20 @@
|
|||||||
],
|
],
|
||||||
"description": "The Illuminate Filesystem package.",
|
"description": "The Illuminate Filesystem package.",
|
||||||
"homepage": "https://laravel.com",
|
"homepage": "https://laravel.com",
|
||||||
"time": "2018-08-14T19:42:44+00:00"
|
"time": "2018-10-24T12:49:16+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "illuminate/support",
|
"name": "illuminate/support",
|
||||||
"version": "v5.7.8",
|
"version": "v5.7.11",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/illuminate/support.git",
|
"url": "https://github.com/illuminate/support.git",
|
||||||
"reference": "c7583db6703a36b7fa76254073046e0a920ed276"
|
"reference": "45bfc0cd080c51946f61c04e324c2b4c6df58a9d"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/illuminate/support/zipball/c7583db6703a36b7fa76254073046e0a920ed276",
|
"url": "https://api.github.com/repos/illuminate/support/zipball/45bfc0cd080c51946f61c04e324c2b4c6df58a9d",
|
||||||
"reference": "c7583db6703a36b7fa76254073046e0a920ed276",
|
"reference": "45bfc0cd080c51946f61c04e324c2b4c6df58a9d",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -399,20 +400,20 @@
|
|||||||
],
|
],
|
||||||
"description": "The Illuminate Support package.",
|
"description": "The Illuminate Support package.",
|
||||||
"homepage": "https://laravel.com",
|
"homepage": "https://laravel.com",
|
||||||
"time": "2018-10-04T13:27:30+00:00"
|
"time": "2018-10-22T17:36:06+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "illuminate/view",
|
"name": "illuminate/view",
|
||||||
"version": "v5.7.8",
|
"version": "v5.7.11",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/illuminate/view.git",
|
"url": "https://github.com/illuminate/view.git",
|
||||||
"reference": "86b8c60e502286135d9c91b0836a58445c4998b5"
|
"reference": "97dbb6910aa5df5a7414877da89b7520f4260a58"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/illuminate/view/zipball/86b8c60e502286135d9c91b0836a58445c4998b5",
|
"url": "https://api.github.com/repos/illuminate/view/zipball/97dbb6910aa5df5a7414877da89b7520f4260a58",
|
||||||
"reference": "86b8c60e502286135d9c91b0836a58445c4998b5",
|
"reference": "97dbb6910aa5df5a7414877da89b7520f4260a58",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -447,7 +448,7 @@
|
|||||||
],
|
],
|
||||||
"description": "The Illuminate View package.",
|
"description": "The Illuminate View package.",
|
||||||
"homepage": "https://laravel.com",
|
"homepage": "https://laravel.com",
|
||||||
"time": "2018-10-02T13:51:18+00:00"
|
"time": "2018-10-11T15:32:19+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "morris/lessql",
|
"name": "morris/lessql",
|
||||||
|
@@ -38,6 +38,9 @@ DefaultUserSetting('auto_night_mode_time_range_from', "20:00"); // Format HH:mm
|
|||||||
DefaultUserSetting('auto_night_mode_time_range_to', "07:00"); // Format HH:mm
|
DefaultUserSetting('auto_night_mode_time_range_to', "07:00"); // Format HH:mm
|
||||||
DefaultUserSetting('auto_night_mode_time_range_goes_over_midnight', true); // If the time range above goes over midnight
|
DefaultUserSetting('auto_night_mode_time_range_goes_over_midnight', true); // If the time range above goes over midnight
|
||||||
DefaultUserSetting('currently_inside_night_mode_range', false); // If we're currently inside of night mode time range (this is not user configurable, but stored as a user setting because it's evaluated client side to be able to use the client time instead of the maybe different server time)
|
DefaultUserSetting('currently_inside_night_mode_range', false); // If we're currently inside of night mode time range (this is not user configurable, but stored as a user setting because it's evaluated client side to be able to use the client time instead of the maybe different server time)
|
||||||
|
DefaultUserSetting('product_presets_location_id', -1); // Default location id for new products (-1 means no location is preset)
|
||||||
|
DefaultUserSetting('product_presets_product_group_id', -1); // Default product group id for new products (-1 means no product group is preset)
|
||||||
|
DefaultUserSetting('product_presets_qu_id', -1); // Default quantity unit id for new products (-1 means no quantity unit is preset)
|
||||||
|
|
||||||
# If the page should be automatically reloaded when there was
|
# If the page should be automatically reloaded when there was
|
||||||
# an external change
|
# an external change
|
||||||
|
@@ -44,7 +44,9 @@ class BaseController
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$usersService = new UsersService();
|
$usersService = new UsersService();
|
||||||
$container->view->set('userSettings', $usersService->GetUserSettings(GROCY_USER_ID));
|
if (defined('GROCY_USER_ID')) {
|
||||||
|
$container->view->set('userSettings', $usersService->GetUserSettings(GROCY_USER_ID));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (\Exception $ex)
|
catch (\Exception $ex)
|
||||||
{
|
{
|
||||||
|
@@ -24,8 +24,8 @@ class BatteriesApiController extends BaseApiController
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$this->BatteriesService->TrackChargeCycle($args['batteryId'], $trackedTime);
|
$chargeCycleId = $this->BatteriesService->TrackChargeCycle($args['batteryId'], $trackedTime);
|
||||||
return $this->VoidApiActionResponse($response);
|
return $this->ApiResponse(array('charge_cycle_id' => $chargeCycleId));
|
||||||
}
|
}
|
||||||
catch (\Exception $ex)
|
catch (\Exception $ex)
|
||||||
{
|
{
|
||||||
@@ -49,4 +49,17 @@ class BatteriesApiController extends BaseApiController
|
|||||||
{
|
{
|
||||||
return $this->ApiResponse($this->BatteriesService->GetCurrent());
|
return $this->ApiResponse($this->BatteriesService->GetCurrent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function UndoChargeCycle(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$this->ApiResponse($this->BatteriesService->UndoChargeCycle($args['chargeCycleId']));
|
||||||
|
return $this->ApiResponse(array('success' => true));
|
||||||
|
}
|
||||||
|
catch (\Exception $ex)
|
||||||
|
{
|
||||||
|
return $this->VoidApiActionResponse($response, false, 400, $ex->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -53,4 +53,12 @@ class BatteriesController extends BaseController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function Journal(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||||
|
{
|
||||||
|
return $this->AppContainer->view->render($response, 'batteriesjournal', [
|
||||||
|
'chargeCycles' => $this->Database->battery_charge_cycles()->orderBy('tracked_time', 'DESC'),
|
||||||
|
'batteries' => $this->Database->batteries()->orderBy('name')
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -30,8 +30,8 @@ class ChoresApiController extends BaseApiController
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$this->ChoresService->TrackChore($args['choreId'], $trackedTime, $doneBy);
|
$choreExecutionId = $this->ChoresService->TrackChore($args['choreId'], $trackedTime, $doneBy);
|
||||||
return $this->VoidApiActionResponse($response);
|
return $this->ApiResponse(array('chore_execution_id' => $choreExecutionId));
|
||||||
}
|
}
|
||||||
catch (\Exception $ex)
|
catch (\Exception $ex)
|
||||||
{
|
{
|
||||||
@@ -55,4 +55,17 @@ class ChoresApiController extends BaseApiController
|
|||||||
{
|
{
|
||||||
return $this->ApiResponse($this->ChoresService->GetCurrent());
|
return $this->ApiResponse($this->ChoresService->GetCurrent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function UndoChoreExecution(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$this->ApiResponse($this->ChoresService->UndoChoreExecution($args['executionId']));
|
||||||
|
return $this->ApiResponse(array('success' => true));
|
||||||
|
}
|
||||||
|
catch (\Exception $ex)
|
||||||
|
{
|
||||||
|
return $this->VoidApiActionResponse($response, false, 400, $ex->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -38,9 +38,9 @@ class ChoresController extends BaseController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function Analysis(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
public function Journal(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||||
{
|
{
|
||||||
return $this->AppContainer->view->render($response, 'choresanalysis', [
|
return $this->AppContainer->view->render($response, 'choresjournal', [
|
||||||
'choresLog' => $this->Database->chores_log()->orderBy('tracked_time', 'DESC'),
|
'choresLog' => $this->Database->chores_log()->orderBy('tracked_time', 'DESC'),
|
||||||
'chores' => $this->Database->chores()->orderBy('name'),
|
'chores' => $this->Database->chores()->orderBy('name'),
|
||||||
'users' => $this->Database->users()->orderBy('username')
|
'users' => $this->Database->users()->orderBy('username')
|
||||||
|
@@ -6,7 +6,7 @@ class GenericEntityApiController extends BaseApiController
|
|||||||
{
|
{
|
||||||
public function GetObjects(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
public function GetObjects(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||||
{
|
{
|
||||||
if ($this->IsValidEntity($args['entity']))
|
if ($this->IsValidEntity($args['entity']) && !$this->IsEntityWithPreventedListing($args['entity']))
|
||||||
{
|
{
|
||||||
return $this->ApiResponse($this->Database->{$args['entity']}());
|
return $this->ApiResponse($this->Database->{$args['entity']}());
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,7 @@ class GenericEntityApiController extends BaseApiController
|
|||||||
|
|
||||||
public function GetObject(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
public function GetObject(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||||
{
|
{
|
||||||
if ($this->IsValidEntity($args['entity']))
|
if ($this->IsValidEntity($args['entity']) && !$this->IsEntityWithPreventedListing($args['entity']))
|
||||||
{
|
{
|
||||||
return $this->ApiResponse($this->Database->{$args['entity']}($args['objectId']));
|
return $this->ApiResponse($this->Database->{$args['entity']}($args['objectId']));
|
||||||
}
|
}
|
||||||
@@ -77,4 +77,9 @@ class GenericEntityApiController extends BaseApiController
|
|||||||
{
|
{
|
||||||
return in_array($entity, $this->OpenApiSpec->components->internalSchemas->ExposedEntity->enum);
|
return in_array($entity, $this->OpenApiSpec->components->internalSchemas->ExposedEntity->enum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function IsEntityWithPreventedListing($entity)
|
||||||
|
{
|
||||||
|
return in_array($entity, $this->OpenApiSpec->components->internalSchemas->ExposedEntitiesPreventListing->enum);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -30,7 +30,7 @@ class LoginController extends BaseController
|
|||||||
if ($user !== null && password_verify($inputPassword, $user->password))
|
if ($user !== null && password_verify($inputPassword, $user->password))
|
||||||
{
|
{
|
||||||
$sessionKey = $this->SessionService->CreateSession($user->id, $stayLoggedInPermanently);
|
$sessionKey = $this->SessionService->CreateSession($user->id, $stayLoggedInPermanently);
|
||||||
setcookie($this->SessionCookieName, $sessionKey, time() + 31220640000); // Cookie expires in 999 years, but session validity is up to SessionService
|
setcookie($this->SessionCookieName, $sessionKey, intval(time() + 31220640000)); // Cookie expires in 999 years, but session validity is up to SessionService
|
||||||
|
|
||||||
if (password_needs_rehash($user->password, PASSWORD_DEFAULT))
|
if (password_needs_rehash($user->password, PASSWORD_DEFAULT))
|
||||||
{
|
{
|
||||||
|
@@ -23,18 +23,21 @@ class RecipesController extends BaseController
|
|||||||
if (isset($request->getQueryParams()['recipe']))
|
if (isset($request->getQueryParams()['recipe']))
|
||||||
{
|
{
|
||||||
$selectedRecipe = $this->Database->recipes($request->getQueryParams()['recipe']);
|
$selectedRecipe = $this->Database->recipes($request->getQueryParams()['recipe']);
|
||||||
$selectedRecipePositions = $this->Database->recipes_pos()->where('recipe_id', $request->getQueryParams()['recipe']);
|
$selectedRecipePositions = $this->Database->recipes_pos()->where('recipe_id', $request->getQueryParams()['recipe'])->orderBy('ingredient_group');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foreach ($recipes as $recipe)
|
foreach ($recipes as $recipe)
|
||||||
{
|
{
|
||||||
$selectedRecipe = $recipe;
|
$selectedRecipe = $recipe;
|
||||||
$selectedRecipePositions = $this->Database->recipes_pos()->where('recipe_id', $recipe->id);
|
$selectedRecipePositions = $this->Database->recipes_pos()->where('recipe_id', $recipe->id)->orderBy('ingredient_group');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$selectedRecipeSubRecipes = $this->Database->recipes()->where('id IN (SELECT includes_recipe_id FROM recipes_nestings_resolved WHERE recipe_id = :1 AND includes_recipe_id != :1)', $selectedRecipe->id)->orderBy('name')->fetchAll();
|
||||||
|
$selectedRecipeSubRecipesPositions = $this->Database->recipes_pos()->where('recipe_id IN (SELECT includes_recipe_id FROM recipes_nestings_resolved WHERE recipe_id = :1 AND includes_recipe_id != :1)', $selectedRecipe->id)->orderBy('ingredient_group')->fetchAll();
|
||||||
|
|
||||||
return $this->AppContainer->view->render($response, 'recipes', [
|
return $this->AppContainer->view->render($response, 'recipes', [
|
||||||
'recipes' => $recipes,
|
'recipes' => $recipes,
|
||||||
'recipesFulfillment' => $this->RecipesService->GetRecipesFulfillment(),
|
'recipesFulfillment' => $this->RecipesService->GetRecipesFulfillment(),
|
||||||
@@ -42,7 +45,9 @@ class RecipesController extends BaseController
|
|||||||
'selectedRecipe' => $selectedRecipe,
|
'selectedRecipe' => $selectedRecipe,
|
||||||
'selectedRecipePositions' => $selectedRecipePositions,
|
'selectedRecipePositions' => $selectedRecipePositions,
|
||||||
'products' => $this->Database->products(),
|
'products' => $this->Database->products(),
|
||||||
'quantityunits' => $this->Database->quantity_units()
|
'quantityunits' => $this->Database->quantity_units(),
|
||||||
|
'selectedRecipeSubRecipes' => $selectedRecipeSubRecipes,
|
||||||
|
'selectedRecipeSubRecipesPositions' => $selectedRecipeSubRecipesPositions
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +71,9 @@ class RecipesController extends BaseController
|
|||||||
'products' => $this->Database->products(),
|
'products' => $this->Database->products(),
|
||||||
'quantityunits' => $this->Database->quantity_units(),
|
'quantityunits' => $this->Database->quantity_units(),
|
||||||
'recipesFulfillment' => $this->RecipesService->GetRecipesFulfillment(),
|
'recipesFulfillment' => $this->RecipesService->GetRecipesFulfillment(),
|
||||||
'recipesSumFulfillment' => $this->RecipesService->GetRecipesSumFulfillment()
|
'recipesSumFulfillment' => $this->RecipesService->GetRecipesSumFulfillment(),
|
||||||
|
'recipes' => $this->Database->recipes()->orderBy('name'),
|
||||||
|
'recipeNestings' => $this->Database->recipes_nestings()->where('recipe_id', $recipeId)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -60,8 +60,8 @@ class StockApiController extends BaseApiController
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$this->StockService->AddProduct($args['productId'], $args['amount'], $bestBeforeDate, $transactionType, date('Y-m-d'), $price);
|
$bookingId = $this->StockService->AddProduct($args['productId'], $args['amount'], $bestBeforeDate, $transactionType, date('Y-m-d'), $price);
|
||||||
return $this->VoidApiActionResponse($response);
|
return $this->ApiResponse(array('booking_id' => $bookingId));
|
||||||
}
|
}
|
||||||
catch (\Exception $ex)
|
catch (\Exception $ex)
|
||||||
{
|
{
|
||||||
@@ -85,8 +85,8 @@ class StockApiController extends BaseApiController
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$this->StockService->ConsumeProduct($args['productId'], $args['amount'], $spoiled, $transactionType);
|
$bookingId = $this->StockService->ConsumeProduct($args['productId'], $args['amount'], $spoiled, $transactionType);
|
||||||
return $this->VoidApiActionResponse($response);
|
return $this->ApiResponse(array('booking_id' => $bookingId));
|
||||||
}
|
}
|
||||||
catch (\Exception $ex)
|
catch (\Exception $ex)
|
||||||
{
|
{
|
||||||
@@ -104,8 +104,8 @@ class StockApiController extends BaseApiController
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$this->StockService->InventoryProduct($args['productId'], $args['newAmount'], $bestBeforeDate);
|
$bookingId = $this->StockService->InventoryProduct($args['productId'], $args['newAmount'], $bestBeforeDate);
|
||||||
return $this->VoidApiActionResponse($response);
|
return $this->ApiResponse(array('booking_id' => $bookingId));
|
||||||
}
|
}
|
||||||
catch (\Exception $ex)
|
catch (\Exception $ex)
|
||||||
{
|
{
|
||||||
@@ -165,4 +165,17 @@ class StockApiController extends BaseApiController
|
|||||||
return $this->VoidApiActionResponse($response, false, 400, $ex->getMessage());
|
return $this->VoidApiActionResponse($response, false, 400, $ex->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function UndoBooking(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$this->ApiResponse($this->StockService->UndoBooking($args['bookingId']));
|
||||||
|
return $this->ApiResponse(array('success' => true));
|
||||||
|
}
|
||||||
|
catch (\Exception $ex)
|
||||||
|
{
|
||||||
|
return $this->VoidApiActionResponse($response, false, 400, $ex->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -23,7 +23,8 @@ class StockController extends BaseController
|
|||||||
'locations' => $this->Database->locations()->orderBy('name'),
|
'locations' => $this->Database->locations()->orderBy('name'),
|
||||||
'currentStock' => $this->StockService->GetCurrentStock(),
|
'currentStock' => $this->StockService->GetCurrentStock(),
|
||||||
'missingProducts' => $this->StockService->GetMissingProducts(),
|
'missingProducts' => $this->StockService->GetMissingProducts(),
|
||||||
'nextXDays' => 5
|
'nextXDays' => 5,
|
||||||
|
'productGroups' => $this->Database->product_groups()->orderBy('name')
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,6 +70,15 @@ class StockController extends BaseController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function ProductDefaults(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||||
|
{
|
||||||
|
return $this->AppContainer->view->render($response, 'productpresets', [
|
||||||
|
'locations' => $this->Database->locations()->orderBy('name'),
|
||||||
|
'quantityunits' => $this->Database->quantity_units()->orderBy('name'),
|
||||||
|
'productGroups' => $this->Database->product_groups()->orderBy('name')
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
public function LocationsList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
public function LocationsList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||||
{
|
{
|
||||||
return $this->AppContainer->view->render($response, 'locations', [
|
return $this->AppContainer->view->render($response, 'locations', [
|
||||||
@@ -182,4 +192,13 @@ class StockController extends BaseController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function Journal(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||||
|
{
|
||||||
|
return $this->AppContainer->view->render($response, 'stockjournal', [
|
||||||
|
'stockLog' => $this->Database->stock_log()->orderBy('row_created_timestamp', 'DESC'),
|
||||||
|
'products' => $this->Database->products()->orderBy('name'),
|
||||||
|
'quantityunits' => $this->Database->quantity_units()->orderBy('name')
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1288,6 +1288,47 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/stock/undo-booking/{bookingId}": {
|
||||||
|
"get": {
|
||||||
|
"description": "Undoes a booking",
|
||||||
|
"tags": [
|
||||||
|
"Stock"
|
||||||
|
],
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "bookingId",
|
||||||
|
"required": true,
|
||||||
|
"description": "A valid stock booking id",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A VoidApiActionResponse object",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/VoidApiActionResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "A VoidApiActionResponse object (possible errors are: Not existing booking)",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ErrorExampleVoidApiActionResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/recipes/add-not-fulfilled-products-to-shopping-list/{recipeId}": {
|
"/recipes/add-not-fulfilled-products-to-shopping-list/{recipeId}": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "Adds all missing products for the given recipe to the shopping list",
|
"description": "Adds all missing products for the given recipe to the shopping list",
|
||||||
@@ -1473,6 +1514,47 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/chores/undo-chore-execution/{executionId}": {
|
||||||
|
"get": {
|
||||||
|
"description": "Undoes a chore execution",
|
||||||
|
"tags": [
|
||||||
|
"Chores"
|
||||||
|
],
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "executionId",
|
||||||
|
"required": true,
|
||||||
|
"description": "A valid chore execution id",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A VoidApiActionResponse object",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/VoidApiActionResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "A VoidApiActionResponse object (possible errors are: Not existing booking)",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ErrorExampleVoidApiActionResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/batteries/track-charge-cycle/{batteryId}": {
|
"/batteries/track-charge-cycle/{batteryId}": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "Tracks a charge cycle of the given battery",
|
"description": "Tracks a charge cycle of the given battery",
|
||||||
@@ -1588,6 +1670,47 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/batteries/undo-charge-cycle/{chargeCycleId}": {
|
||||||
|
"get": {
|
||||||
|
"description": "Undoes a chore execution",
|
||||||
|
"tags": [
|
||||||
|
"Batteries"
|
||||||
|
],
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "chargeCycleId",
|
||||||
|
"required": true,
|
||||||
|
"description": "A valid charge cycle id",
|
||||||
|
"schema": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A VoidApiActionResponse object",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/VoidApiActionResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "A VoidApiActionResponse object (possible errors are: Not existing booking)",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ErrorExampleVoidApiActionResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/tasks/get-current": {
|
"/tasks/get-current": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "Returns all tasks which are not done yet",
|
"description": "Returns all tasks which are not done yet",
|
||||||
@@ -1675,10 +1798,18 @@
|
|||||||
"shopping_list",
|
"shopping_list",
|
||||||
"recipes",
|
"recipes",
|
||||||
"recipes_pos",
|
"recipes_pos",
|
||||||
|
"recipes_nestings",
|
||||||
"tasks",
|
"tasks",
|
||||||
"task_categories",
|
"task_categories",
|
||||||
"product_groups",
|
"product_groups",
|
||||||
"equipment"
|
"equipment",
|
||||||
|
"api_keys"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ExposedEntitiesPreventListing": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"api_keys"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"StockTransactionType": {
|
"StockTransactionType": {
|
||||||
|
@@ -184,7 +184,7 @@ return array(
|
|||||||
'Last done by' => 'Zuletzt ausgeführt von',
|
'Last done by' => 'Zuletzt ausgeführt von',
|
||||||
'Unknown' => 'Unbekannt',
|
'Unknown' => 'Unbekannt',
|
||||||
'Filter by chore' => 'Nach Hausarbeit filtern',
|
'Filter by chore' => 'Nach Hausarbeit filtern',
|
||||||
'Chores analysis' => 'Hausarbeiten Analyse',
|
'Chores journal' => 'Hausarbeitenjournal',
|
||||||
'0 means suggestions for the next charge cycle are disabled' => '0 bedeutet dass Vorschläge für den nächsten Ladezyklus deaktiviert sind',
|
'0 means suggestions for the next charge cycle are disabled' => '0 bedeutet dass Vorschläge für den nächsten Ladezyklus deaktiviert sind',
|
||||||
'Charge cycle interval (days)' => 'Ladezyklusintervall (Tage)',
|
'Charge cycle interval (days)' => 'Ladezyklusintervall (Tage)',
|
||||||
'Last price' => 'Letzter Preis',
|
'Last price' => 'Letzter Preis',
|
||||||
@@ -277,11 +277,40 @@ return array(
|
|||||||
'Current instruction manual' => 'Aktuelle Bedienungsanleitung',
|
'Current instruction manual' => 'Aktuelle Bedienungsanleitung',
|
||||||
'No instruction manual available' => 'Keine Bedienungsanleitung vorhanden',
|
'No instruction manual available' => 'Keine Bedienungsanleitung vorhanden',
|
||||||
'The current instruction manual will be deleted when you save the equipment' => 'Die aktuelle Bedienungsanleitung wird beim Speichern des Geräts gelöscht',
|
'The current instruction manual will be deleted when you save the equipment' => 'Die aktuelle Bedienungsanleitung wird beim Speichern des Geräts gelöscht',
|
||||||
|
'No picture available' => 'Kein Bild vorhanden',
|
||||||
|
'Filter by product group' => 'Nach Produktgruppe filtern',
|
||||||
|
'Presets for new products' => 'Vorgaben für neue Produkte',
|
||||||
|
'Included recipes' => 'Enthaltene Rezepte',
|
||||||
|
'A recipe is required' => 'Ein Rezept ist erforderlich',
|
||||||
|
'Add included recipe' => 'Enthaltenes Rezept hinzufügen',
|
||||||
|
'Edit included recipe' => 'Enthaltenes Rezept bearbeiten',
|
||||||
|
'Group' => 'Gruppe',
|
||||||
|
'This will be used as a headline to group ingredients together' => 'Dies wird als Überschrift verwendet, um Zutaten zusammenzufassen',
|
||||||
|
'Journal' => 'Journal',
|
||||||
|
'Stock journal' => 'Bestandsjournal',
|
||||||
|
'Filter by product' => 'Nach Produkt filtern',
|
||||||
|
'Booking time' => 'Buchungszeit',
|
||||||
|
'Booking type' => 'Buchungsart',
|
||||||
|
'Undo booking' => 'Buchung rückgängig machen',
|
||||||
|
'Undone on' => 'Rückgängig gemacht am',
|
||||||
|
'Batteries journal' => 'Batteriejournal',
|
||||||
|
'Filter by battery' => 'Nach Batterie filtern',
|
||||||
|
'Undo charge cycle' => 'Ladezyklus rückgängig machen',
|
||||||
|
'Undo chore execution' => 'Ausführung rückgängig machen',
|
||||||
|
'Chore execution successfully undone' => 'Ausführung erfolgreich rückgängig gemacht',
|
||||||
|
'Undo' => 'Rückgängig machen',
|
||||||
|
'Booking successfully undone' => 'Buchung erfolgreich rückgängig gemacht',
|
||||||
|
'Charge cycle successfully undone' => 'Ladezyklus erfolgreich rückgängig gemacht',
|
||||||
|
|
||||||
//Constants
|
//Constants - Chore types
|
||||||
'manually' => 'Manuell',
|
'manually' => 'Manuell',
|
||||||
'dynamic-regular' => 'Dynamisch regelmäßig',
|
'dynamic-regular' => 'Dynamisch regelmäßig',
|
||||||
|
|
||||||
|
//Constants - Stock transaction types
|
||||||
|
'purchase' => 'Einkauf',
|
||||||
|
'consume' => 'Verbrauch',
|
||||||
|
'inventory-correction' => 'Inventur-Korrektur',
|
||||||
|
|
||||||
//Technical component translations
|
//Technical component translations
|
||||||
'timeago_locale' => 'de',
|
'timeago_locale' => 'de',
|
||||||
'timeago_nan' => 'vor NaN Jahren',
|
'timeago_nan' => 'vor NaN Jahren',
|
||||||
@@ -361,5 +390,15 @@ return array(
|
|||||||
'Vegetables/Fruits' => 'Obst/Gemüse',
|
'Vegetables/Fruits' => 'Obst/Gemüse',
|
||||||
'Refrigerated products' => 'Kühlregal',
|
'Refrigerated products' => 'Kühlregal',
|
||||||
'Coffee machine' => 'Kaffeemaschine',
|
'Coffee machine' => 'Kaffeemaschine',
|
||||||
'Dishwasher' => 'Spülmaschine'
|
'Dishwasher' => 'Spülmaschine',
|
||||||
|
'Liter' => 'Liter',
|
||||||
|
'Liters' => 'Liter',
|
||||||
|
'Bottle' => 'Flasche',
|
||||||
|
'Bottles' => 'Flaschen',
|
||||||
|
'Milk' => 'Milch',
|
||||||
|
'Chocolate sauce' => 'Schokoladensoße',
|
||||||
|
'Milliliters' => 'Milliliter',
|
||||||
|
'Milliliter' => 'Milliliter',
|
||||||
|
'Bottom' => 'Boden',
|
||||||
|
'Topping' => 'Belag'
|
||||||
);
|
);
|
||||||
|
@@ -1,10 +1,15 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
//Constants
|
//Constants - Chore types
|
||||||
'manually' => 'Manually',
|
'manually' => 'Manually',
|
||||||
'dynamic-regular' => 'Dynamic regular',
|
'dynamic-regular' => 'Dynamic regular',
|
||||||
|
|
||||||
|
//Constants - Stock transaction types
|
||||||
|
'purchase' => 'Purchase',
|
||||||
|
'consume' => 'Consume',
|
||||||
|
'inventory-correction' => 'Inventory correction',
|
||||||
|
|
||||||
//Technical component translations
|
//Technical component translations
|
||||||
'timeago_locale' => 'en',
|
'timeago_locale' => 'en',
|
||||||
'timeago_nan' => 'NaN years ago',
|
'timeago_nan' => 'NaN years ago',
|
||||||
|
@@ -9,14 +9,14 @@ return array(
|
|||||||
'Amount' => 'Antall',
|
'Amount' => 'Antall',
|
||||||
'Next best before date' => 'Kommende best før dato',
|
'Next best before date' => 'Kommende best før dato',
|
||||||
'Logout' => 'Logg ut',
|
'Logout' => 'Logg ut',
|
||||||
'Chores overview' => 'Oversikt Husarbeid',
|
'Chores overview' => 'Oversikt husarbeid',
|
||||||
'Batteries overview' => 'Oversikt Batteri',
|
'Batteries overview' => 'Oversikt batteri',
|
||||||
'Purchase' => 'Innkjøp',
|
'Purchase' => 'Innkjøp',
|
||||||
'Consume' => 'Forbruk produkt',
|
'Consume' => 'Forbruk produkt',
|
||||||
'Inventory' => 'Endre Husholdning',
|
'Inventory' => 'Endre husholdning',
|
||||||
'Shopping list' => 'Handleliste',
|
'Shopping list' => 'Handleliste',
|
||||||
'Chore tracking' => 'Logge Husarbeid',
|
'Chore tracking' => 'Logge husarbeid',
|
||||||
'Battery tracking' => 'Batteri Ladesyklus',
|
'Battery tracking' => 'Batteri ladesyklus',
|
||||||
'Products' => 'Produkter',
|
'Products' => 'Produkter',
|
||||||
'Locations' => 'Lokasjoner',
|
'Locations' => 'Lokasjoner',
|
||||||
'Quantity units' => 'Forpakning',
|
'Quantity units' => 'Forpakning',
|
||||||
@@ -41,9 +41,9 @@ return array(
|
|||||||
'New amount' => 'Nytt antall',
|
'New amount' => 'Nytt antall',
|
||||||
'Note' => 'Info',
|
'Note' => 'Info',
|
||||||
'Tracked time' => 'Tid utført/ ladet',
|
'Tracked time' => 'Tid utført/ ladet',
|
||||||
'Chore overview' => 'Oversikt Husarbeid',
|
'Chore overview' => 'Oversikt husarbeid',
|
||||||
'Tracked count' => 'Antall utførelser/ ladninger',
|
'Tracked count' => 'Antall utførelser/ ladninger',
|
||||||
'Battery overview' => 'Batteri Oversikt',
|
'Battery overview' => 'Batteri oversikt',
|
||||||
'Charge cycles count' => 'Antall ladesykluser',
|
'Charge cycles count' => 'Antall ladesykluser',
|
||||||
'Create shopping list item' => 'Opprett handelisteoppføring',
|
'Create shopping list item' => 'Opprett handelisteoppføring',
|
||||||
'Edit shopping list item' => 'Endre på handlelistoppføring',
|
'Edit shopping list item' => 'Endre på handlelistoppføring',
|
||||||
@@ -53,9 +53,9 @@ return array(
|
|||||||
'Name' => 'Navn',
|
'Name' => 'Navn',
|
||||||
'Location' => 'Lokasjon',
|
'Location' => 'Lokasjon',
|
||||||
'Min. stock amount' => 'Minimums antall for husholdingen',
|
'Min. stock amount' => 'Minimums antall for husholdingen',
|
||||||
'QU purchase' => 'FPK innkjøp',
|
'QU purchase' => 'Forpakingsfaktor innkjøp',
|
||||||
'QU stock' => 'FPK husholdning',
|
'QU stock' => 'Forpakingsfaktor husholdning',
|
||||||
'QU factor' => 'FPK faktor',
|
'QU factor' => 'Forpakingsfaktor',
|
||||||
'Description' => 'Beskrivelse',
|
'Description' => 'Beskrivelse',
|
||||||
'Create product' => 'Opprett produkt',
|
'Create product' => 'Opprett produkt',
|
||||||
'Barcode(s)' => 'Strekkode(r)',
|
'Barcode(s)' => 'Strekkode(r)',
|
||||||
@@ -87,16 +87,16 @@ return array(
|
|||||||
'Username' => 'Brukernavn',
|
'Username' => 'Brukernavn',
|
||||||
'Password' => 'Passord',
|
'Password' => 'Passord',
|
||||||
'Invalid credentials, please try again' => 'Feil brukernavn og/eller passord, prøv igjen',
|
'Invalid credentials, please try again' => 'Feil brukernavn og/eller passord, prøv igjen',
|
||||||
'Are you sure to delete battery "#1"?' => 'Er du sikker du ønsker å slette Batteri "#1"?',
|
'Are you sure to delete battery "#1"?' => 'Er du sikker du ønsker å slette batteri "#1"?',
|
||||||
'Yes' => 'Ja',
|
'Yes' => 'Ja',
|
||||||
'No' => 'Nei',
|
'No' => 'Nei',
|
||||||
'Are you sure to delete chore "#1"?' => 'Er du sikker på du ønsker å slette husarbeid oppgave "#1"?',
|
'Are you sure to delete chore "#1"?' => 'Er du sikker på du ønsker å slette husarbeid oppgave "#1"?',
|
||||||
'"#1" could not be resolved to a product, how do you want to proceed?' => '"#1" kunne ikke bli tildelt et produkt, hvordan ønsker du å fortsette?',
|
'"#1" could not be resolved to a product, how do you want to proceed?' => '"#1" kunne ikke bli tildelt et produkt, hvordan ønsker du å fortsette?',
|
||||||
'Create or assign product' => 'Opprett eller tildel til produkt',
|
'Create or assign product' => 'Opprett eller tildel til et produkt',
|
||||||
'Cancel' => 'Avbryt',
|
'Cancel' => 'Avbryt',
|
||||||
'Add as new product' => 'Legg til som nytt produkt',
|
'Add as new product' => 'Legg til som nytt produkt',
|
||||||
'Add as barcode to existing product' => 'Legg til strekkode til allerede eksisterende produkt',
|
'Add as barcode to existing product' => 'Legg til strekkode til allerede eksisterende produkt',
|
||||||
'Add as new product and prefill barcode' => 'Legg til som nytt produkt med forhåndsutfylt strekkode',
|
'Add as new product and prefill barcode' => 'Legg til som nytt produkt med forhåndsfylt strekkode',
|
||||||
'Are you sure to delete quantity unit "#1"?' => 'Er du sikker du ønsker å slette forpakning "#1"?',
|
'Are you sure to delete quantity unit "#1"?' => 'Er du sikker du ønsker å slette forpakning "#1"?',
|
||||||
'Are you sure to delete product "#1"?' => 'Er du sikker du ønsker å slette produkt "#1"?',
|
'Are you sure to delete product "#1"?' => 'Er du sikker du ønsker å slette produkt "#1"?',
|
||||||
'Are you sure to delete location "#1"?' => 'Er du sikker du ønsker å slette lokasjon "#1"?',
|
'Are you sure to delete location "#1"?' => 'Er du sikker du ønsker å slette lokasjon "#1"?',
|
||||||
@@ -114,10 +114,10 @@ return array(
|
|||||||
'Removed #1 #2 of #3 from stock' => 'Fjernet #1 #2 #3 fra husholdningen',
|
'Removed #1 #2 of #3 from stock' => 'Fjernet #1 #2 #3 fra husholdningen',
|
||||||
'About grocy' => 'Om Grocy',
|
'About grocy' => 'Om Grocy',
|
||||||
'Close' => 'Lukk',
|
'Close' => 'Lukk',
|
||||||
'#1 batteries are due to be charged within the next #2 days' => '#1 Batteri må lades innen de #2 neste dagene',
|
'#1 batteries are due to be charged within the next #2 days' => '#1 batteri må lades innen de #2 neste dagene',
|
||||||
'#1 batteries are overdue to be charged' => '#1 Batteri har gått over fristen for å bli ladet opp',
|
'#1 batteries are overdue to be charged' => '#1 Batteri har gått over fristen for å bli ladet opp',
|
||||||
'#1 chores are due to be done within the next #2 days' => '#1 husarbeid(s) oppgave(r) skal gjøres inne de #2 neste dagene',
|
'#1 chores are due to be done within the next #2 days' => '#1 husarbeids oppgaver skal gjøres inne de #2 neste dagene',
|
||||||
'#1 chores are overdue to be done' => '#1 husarbeid(s) oppgave(r) har gått over fristen for utførelse',
|
'#1 chores are overdue to be done' => '#1 husarbeids oppgaver har gått over fristen for utførelse',
|
||||||
'Released on' => 'Utgitt',
|
'Released on' => 'Utgitt',
|
||||||
'Consume #3 #1 of #2' => 'Forbruk #3 #1 #2',
|
'Consume #3 #1 of #2' => 'Forbruk #3 #1 #2',
|
||||||
'Added #1 #2 of #3 to stock' => '#1 #2 #3 lagt til i husholdningen',
|
'Added #1 #2 of #3 to stock' => '#1 #2 #3 lagt til i husholdningen',
|
||||||
@@ -132,7 +132,7 @@ return array(
|
|||||||
'Search' => 'Søk',
|
'Search' => 'Søk',
|
||||||
'Not logged in' => 'Ikke logget inn',
|
'Not logged in' => 'Ikke logget inn',
|
||||||
'You have to select a product' => 'Du må velge et produkt',
|
'You have to select a product' => 'Du må velge et produkt',
|
||||||
'You have to select a chore' => 'Du må velge en husarbeid oppgave',
|
'You have to select a chore' => 'Du må velge en husarbeids oppgave',
|
||||||
'You have to select a battery' => 'Du må velge et batteri',
|
'You have to select a battery' => 'Du må velge et batteri',
|
||||||
'A name is required' => 'Vennligst fyll inn et navn',
|
'A name is required' => 'Vennligst fyll inn et navn',
|
||||||
'A location is required' => 'En lokasjon kreves',
|
'A location is required' => 'En lokasjon kreves',
|
||||||
@@ -153,7 +153,7 @@ return array(
|
|||||||
'Are you sure to delete recipe "#1"?' => 'Er du sikker du ønsker å slette oppskrift "#1"?',
|
'Are you sure to delete recipe "#1"?' => 'Er du sikker du ønsker å slette oppskrift "#1"?',
|
||||||
'Are you sure to delete recipe ingredient "#1"?' => 'Er du sikker du ønsker å slette ingrediens "#1" fra oppskriften?',
|
'Are you sure to delete recipe ingredient "#1"?' => 'Er du sikker du ønsker å slette ingrediens "#1" fra oppskriften?',
|
||||||
'Are you sure to empty the shopping list?' => 'Er du sikker du ønsker å slette handlelisten?',
|
'Are you sure to empty the shopping list?' => 'Er du sikker du ønsker å slette handlelisten?',
|
||||||
'Clear list' => 'Tøm liste',
|
'Clear list' => 'Slett handleliste',
|
||||||
'Requirements fulfilled' => 'Har jeg alt jeg trenger for denne oppskriften?',
|
'Requirements fulfilled' => 'Har jeg alt jeg trenger for denne oppskriften?',
|
||||||
'Put missing products on shopping list' => 'Legg manglende produkter til handlelisten',
|
'Put missing products on shopping list' => 'Legg manglende produkter til handlelisten',
|
||||||
'Not enough in stock, #1 ingredients missing' => 'Ikke nok i husholdningen, #1 ingredienser mangler',
|
'Not enough in stock, #1 ingredients missing' => 'Ikke nok i husholdningen, #1 ingredienser mangler',
|
||||||
@@ -184,9 +184,9 @@ return array(
|
|||||||
'Last done by' => 'Sist utført av',
|
'Last done by' => 'Sist utført av',
|
||||||
'Unknown' => 'Ukjent',
|
'Unknown' => 'Ukjent',
|
||||||
'Filter by chore' => 'Filtrér husarbeid',
|
'Filter by chore' => 'Filtrér husarbeid',
|
||||||
'Chores analysis' => 'Statistikk husarbeid',
|
'Chores journal' => 'Statistikk husarbeid',
|
||||||
'0 means suggestions for the next charge cycle are disabled' => '0 betyr neste ladesyklus er avslått',
|
'0 means suggestions for the next charge cycle are disabled' => '0 betyr neste ladesyklus er avslått',
|
||||||
'Charge cycle interval (days)' => 'Ladesyklysintervall (Dager)',
|
'Charge cycle interval (days)' => 'Ladesyklysintervall (dager)',
|
||||||
'Last price' => 'Siste pris',
|
'Last price' => 'Siste pris',
|
||||||
'Price history' => 'Prishistorikk',
|
'Price history' => 'Prishistorikk',
|
||||||
'No price history available' => 'Ingen prishistorikk tilgjengelig',
|
'No price history available' => 'Ingen prishistorikk tilgjengelig',
|
||||||
@@ -198,8 +198,8 @@ return array(
|
|||||||
'#1 product is below defined min. stock amount' => '#1 Produkt er under minimums husholdningsnivå',
|
'#1 product is below defined min. stock amount' => '#1 Produkt er under minimums husholdningsnivå',
|
||||||
'Unit' => 'Enhet',
|
'Unit' => 'Enhet',
|
||||||
'Units' => 'Enheter',
|
'Units' => 'Enheter',
|
||||||
'#1 chore is due to be done within the next #2 days' => '#1 husarbeid oppgave(r) skal gjøres inne de #2 neste dagene',
|
'#1 chore is due to be done within the next #2 days' => '#1 husarbeid oppgave skal gjøres inne de #2 neste dagene',
|
||||||
'#1 chore is overdue to be done' => '#1 husarbeid(s) oppgave(r) har gått over fristen for utførelse',
|
'#1 chore is overdue to be done' => '#1 husarbeid oppgave har gått over fristen for utførelse',
|
||||||
'#1 battery is due to be charged within the next #2 days' => '#1 Batteri må lades innen #2 dager',
|
'#1 battery is due to be charged within the next #2 days' => '#1 Batteri må lades innen #2 dager',
|
||||||
'#1 battery is overdue to be charged' => '#1 Batteri har gått over fristen for å lades',
|
'#1 battery is overdue to be charged' => '#1 Batteri har gått over fristen for å lades',
|
||||||
'#1 unit was automatically added and will apply in addition to the amount entered here' => '#1 enhet ble automatisk lagt til i tillegg til hva som blir skrevet inn her',
|
'#1 unit was automatically added and will apply in addition to the amount entered here' => '#1 enhet ble automatisk lagt til i tillegg til hva som blir skrevet inn her',
|
||||||
@@ -209,8 +209,8 @@ return array(
|
|||||||
'This cannot be lower than #1' => 'Dette kan ikke være lavere enn #1',
|
'This cannot be lower than #1' => 'Dette kan ikke være lavere enn #1',
|
||||||
'-1 means that this product never expires' => '-1 Betyr at dette produktet aldri går ut på dato',
|
'-1 means that this product never expires' => '-1 Betyr at dette produktet aldri går ut på dato',
|
||||||
'Quantity unit' => 'Forpakning',
|
'Quantity unit' => 'Forpakning',
|
||||||
'Only check if a single unit is in stock (a different quantity can then be used above)' => 'Huk av hvis du ønsker å bruke mindre enn forpakningsstørrelse i husholdningen',
|
'Only check if a single unit is in stock (a different quantity can then be used above)' => 'Ønsker du å bruke mindre enn forpakningsstørrelse?',
|
||||||
'Are you sure to consume all ingredients needed by recipe "#1" (ingredients marked with "check only if a single unit is in stock" will be ignored)?' => 'Er du sikker du ønsker å forbruke alle ingredienser for "#1" oppskriften? (Ingredienser merket med "bruke mindre enn forpakningsstørrelse i husholdningen" blir ignorert',
|
'Are you sure to consume all ingredients needed by recipe "#1" (ingredients marked with "check only if a single unit is in stock" will be ignored)?' => 'Er du sikker du ønsker å forbruke alle ingredienser for "#1" oppskriften? (Ingredienser merket med "Ønsker du å bruke mindre enn forpakningsstørrelse?" blir ignorert',
|
||||||
'Removed all ingredients of recipe "#1" from stock' => 'Fjern alle ingredienser for "#1" oppskriften fra husholdningen.',
|
'Removed all ingredients of recipe "#1" from stock' => 'Fjern alle ingredienser for "#1" oppskriften fra husholdningen.',
|
||||||
'Consume all ingredients needed by this recipe' => 'Forbruk alle ingredienser for denne oppskriften',
|
'Consume all ingredients needed by this recipe' => 'Forbruk alle ingredienser for denne oppskriften',
|
||||||
'Click to show technical details' => 'Klikk for å vise teknisk informasjon',
|
'Click to show technical details' => 'Klikk for å vise teknisk informasjon',
|
||||||
@@ -236,7 +236,7 @@ return array(
|
|||||||
'Edit task category' => 'Endre oppgave kategori',
|
'Edit task category' => 'Endre oppgave kategori',
|
||||||
'Create task category' => 'Opprett oppgave kategori',
|
'Create task category' => 'Opprett oppgave kategori',
|
||||||
'Product groups' => 'Produktgrupper',
|
'Product groups' => 'Produktgrupper',
|
||||||
'Ungrouped' => 'Ikke i grupper',
|
'Ungrouped' => 'Mangler gruppe',
|
||||||
'Create product group' => 'Opprett produkt gruppe',
|
'Create product group' => 'Opprett produkt gruppe',
|
||||||
'Edit product group' => 'Endre produkt gruppe',
|
'Edit product group' => 'Endre produkt gruppe',
|
||||||
'Product group' => 'Produktgruppe',
|
'Product group' => 'Produktgruppe',
|
||||||
@@ -277,6 +277,7 @@ return array(
|
|||||||
'Current instruction manual' => 'Nåværende instruksjonsmanual',
|
'Current instruction manual' => 'Nåværende instruksjonsmanual',
|
||||||
'No instruction manual available' => 'Ingen instruksjonsmanual tilgjengelig',
|
'No instruction manual available' => 'Ingen instruksjonsmanual tilgjengelig',
|
||||||
'The current instruction manual will be deleted when you save the equipment' => 'Nåværende instruksjonsmanual vil bli slettet når du lagrer utstyret',
|
'The current instruction manual will be deleted when you save the equipment' => 'Nåværende instruksjonsmanual vil bli slettet når du lagrer utstyret',
|
||||||
|
'No picture available' => 'Ingen bilde tilgjengelig',
|
||||||
|
|
||||||
//Constants
|
//Constants
|
||||||
'manually' => 'Manuel',
|
'manually' => 'Manuel',
|
||||||
@@ -355,11 +356,11 @@ return array(
|
|||||||
'Fork and improve grocy' => 'Fork og forbedre grocy',
|
'Fork and improve grocy' => 'Fork og forbedre grocy',
|
||||||
'Find a solution for what to do when I forget the door keys' => 'Finne på løsning for hva jeg skal gjøre når jeg mister dørnøklene',
|
'Find a solution for what to do when I forget the door keys' => 'Finne på løsning for hva jeg skal gjøre når jeg mister dørnøklene',
|
||||||
'Sweets' => 'Godteri',
|
'Sweets' => 'Godteri',
|
||||||
'Bakery products' => 'Produkt fra bakeren ',
|
'Bakery products' => 'Bakevarer',
|
||||||
'Tinned food' => 'Boksemat',
|
'Tinned food' => 'Boksemat',
|
||||||
'Butchery products' => 'Produkt fra slakteren',
|
'Butchery products' => 'Kjøtt/ Ferskvare',
|
||||||
'Vegetables/Fruits' => 'Frukt/ Grønnsaker',
|
'Vegetables/Fruits' => 'Frukt/ Grønnsaker',
|
||||||
'Refrigerated products' => 'Kjølte produkter'
|
'Refrigerated products' => 'Frysedisk',
|
||||||
'Coffee machine' => 'Kaffetrakter',
|
'Coffee machine' => 'Kaffetrakter',
|
||||||
'Dishwasher' => 'Oppvaskmaskin'
|
'Dishwasher' => 'Oppvaskmaskin'
|
||||||
);
|
);
|
||||||
|
7
migrations/0042.sql
Normal file
7
migrations/0042.sql
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
CREATE TRIGGER cascade_change_qu_id_stock AFTER UPDATE ON products
|
||||||
|
BEGIN
|
||||||
|
UPDATE recipes_pos
|
||||||
|
SET qu_id = (SELECT qu_id_stock FROM products WHERE id = NEW.id)
|
||||||
|
WHERE product_id IN (SELECT id FROM products WHERE id = NEW.id)
|
||||||
|
AND only_check_single_unit_in_stock = 0;
|
||||||
|
END;
|
43
migrations/0043.sql
Normal file
43
migrations/0043.sql
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
CREATE TABLE recipes_nestings (
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
||||||
|
recipe_id INTEGER NOT NULL,
|
||||||
|
includes_recipe_id INTEGER NOT NULL,
|
||||||
|
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime')),
|
||||||
|
|
||||||
|
UNIQUE(recipe_id, includes_recipe_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE VIEW recipes_nestings_resolved
|
||||||
|
AS
|
||||||
|
WITH RECURSIVE r1(recipe_id, includes_recipe_id)
|
||||||
|
AS (
|
||||||
|
SELECT id, id
|
||||||
|
FROM recipes
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
|
||||||
|
SELECT rn.recipe_id, r1.includes_recipe_id
|
||||||
|
FROM recipes_nestings rn, r1 r1
|
||||||
|
WHERE rn.includes_recipe_id = r1.recipe_id
|
||||||
|
LIMIT 100 -- This is just a safety limit to prevent infinite loops due to infinite nested recipes
|
||||||
|
)
|
||||||
|
SELECT *
|
||||||
|
FROM r1;
|
||||||
|
|
||||||
|
DROP VIEW recipes_fulfillment_sum;
|
||||||
|
CREATE VIEW recipes_fulfillment_sum
|
||||||
|
AS
|
||||||
|
SELECT
|
||||||
|
r.id AS recipe_id,
|
||||||
|
IFNULL(MIN(rf.need_fulfilled), 1) AS need_fulfilled,
|
||||||
|
IFNULL(MIN(rf.need_fulfilled_with_shopping_list), 1) AS need_fulfilled_with_shopping_list,
|
||||||
|
(SELECT COUNT(*) FROM recipes_fulfillment WHERE recipe_id IN (SELECT includes_recipe_id FROM recipes_nestings_resolved rnr2 WHERE rnr2.recipe_id = r.id) AND need_fulfilled = 0 AND recipe_pos_id IS NOT NULL) AS missing_products_count
|
||||||
|
FROM recipes r
|
||||||
|
LEFT JOIN recipes_nestings_resolved rnr
|
||||||
|
ON r.id = rnr.recipe_id
|
||||||
|
LEFT JOIN recipes_fulfillment rf
|
||||||
|
ON rnr.includes_recipe_id = rf.recipe_id
|
||||||
|
GROUP BY r.id;
|
||||||
|
|
||||||
|
ALTER TABLE recipes_pos
|
||||||
|
ADD ingredient_group TEXT;
|
26
migrations/0044.sql
Normal file
26
migrations/0044.sql
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
ALTER TABLE stock_log
|
||||||
|
ADD undone TINYINT NOT NULL DEFAULT 0 CHECK(undone IN (0, 1));
|
||||||
|
|
||||||
|
UPDATE stock_log
|
||||||
|
SET undone = 0;
|
||||||
|
|
||||||
|
ALTER TABLE stock_log
|
||||||
|
ADD undone_timestamp DATETIME;
|
||||||
|
|
||||||
|
ALTER TABLE chores_log
|
||||||
|
ADD undone TINYINT NOT NULL DEFAULT 0 CHECK(undone IN (0, 1));
|
||||||
|
|
||||||
|
UPDATE chores_log
|
||||||
|
SET undone = 0;
|
||||||
|
|
||||||
|
ALTER TABLE chores_log
|
||||||
|
ADD undone_timestamp DATETIME;
|
||||||
|
|
||||||
|
ALTER TABLE battery_charge_cycles
|
||||||
|
ADD undone TINYINT NOT NULL DEFAULT 0 CHECK(undone IN (0, 1));
|
||||||
|
|
||||||
|
UPDATE battery_charge_cycles
|
||||||
|
SET undone = 0;
|
||||||
|
|
||||||
|
ALTER TABLE battery_charge_cycles
|
||||||
|
ADD undone_timestamp DATETIME;
|
@@ -26,7 +26,7 @@
|
|||||||
"summernote": "^0.8.10",
|
"summernote": "^0.8.10",
|
||||||
"swagger-ui-dist": "^3.17.3",
|
"swagger-ui-dist": "^3.17.3",
|
||||||
"tagmanager": "https://github.com/max-favilli/tagmanager.git#3.0.2",
|
"tagmanager": "https://github.com/max-favilli/tagmanager.git#3.0.2",
|
||||||
"tempusdominus-bootstrap-4": "^5.0.1",
|
"tempusdominus-bootstrap-4": "^5.1.2",
|
||||||
"timeago": "^1.6.3",
|
"timeago": "^1.6.3",
|
||||||
"toastr": "^2.1.4"
|
"toastr": "^2.1.4"
|
||||||
}
|
}
|
||||||
|
@@ -81,12 +81,6 @@ input::-webkit-inner-spin-button {
|
|||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.centered-dialog .modal-title,
|
|
||||||
.centered-dialog .modal-body {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Navigation style customizations */
|
/* Navigation style customizations */
|
||||||
#mainNav {
|
#mainNav {
|
||||||
background-color: #e5e5e5 !important;
|
background-color: #e5e5e5 !important;
|
||||||
@@ -95,7 +89,8 @@ input::-webkit-inner-spin-button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.navbar-sidenav {
|
.navbar-sidenav {
|
||||||
overflow: hidden;
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
border-top: 2px solid !important;
|
border-top: 2px solid !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -283,9 +283,14 @@ $("form").on("click", "select", function()
|
|||||||
$(".user-setting-control").on("change", function()
|
$(".user-setting-control").on("change", function()
|
||||||
{
|
{
|
||||||
var element = $(this);
|
var element = $(this);
|
||||||
var inputType = element.attr("type").toLowerCase();
|
|
||||||
var settingKey = element.attr("data-setting-key");
|
var settingKey = element.attr("data-setting-key");
|
||||||
|
|
||||||
|
var inputType = "unknown";
|
||||||
|
if (typeof element.attr("type") !== typeof undefined && element.attr("type") !== false)
|
||||||
|
{
|
||||||
|
inputType = element.attr("type").toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
if (inputType === "checkbox")
|
if (inputType === "checkbox")
|
||||||
{
|
{
|
||||||
value = element.is(":checked");
|
value = element.is(":checked");
|
||||||
@@ -338,6 +343,5 @@ ResizeResponsiveEmbeds = function(fillEntireViewport = false)
|
|||||||
}
|
}
|
||||||
$(window).on('resize', function()
|
$(window).on('resize', function()
|
||||||
{
|
{
|
||||||
console.log($("body").hasClass("fullscreen-responsive-embed-active"));
|
ResizeResponsiveEmbeds($("body").hasClass("fullscreen-card"));
|
||||||
ResizeResponsiveEmbeds($("body").hasClass("fullscreen-responsive-embed-active"));
|
|
||||||
});
|
});
|
||||||
|
@@ -22,7 +22,7 @@ setInterval(function()
|
|||||||
{
|
{
|
||||||
if (Grocy.IdleTime >= 50)
|
if (Grocy.IdleTime >= 50)
|
||||||
{
|
{
|
||||||
if (BoolVal(Grocy.UserSettings.auto_reload_on_db_change) && $("form.is-dirty").length === 0)
|
if (BoolVal(Grocy.UserSettings.auto_reload_on_db_change) && $("form.is-dirty").length === 0 && !$("body").hasClass("fullscreen-card"))
|
||||||
{
|
{
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
|
70
public/viewjs/batteriesjournal.js
Normal file
70
public/viewjs/batteriesjournal.js
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
var batteriesJournalTable = $('#batteries-journal-table').DataTable({
|
||||||
|
'paginate': true,
|
||||||
|
'order': [[1, 'desc']],
|
||||||
|
'columnDefs': [
|
||||||
|
{ 'orderable': false, 'targets': 0 }
|
||||||
|
],
|
||||||
|
'language': JSON.parse(L('datatables_localization')),
|
||||||
|
'scrollY': false,
|
||||||
|
'colReorder': true,
|
||||||
|
'stateSave': true,
|
||||||
|
'stateSaveParams': function(settings, data)
|
||||||
|
{
|
||||||
|
data.search.search = "";
|
||||||
|
|
||||||
|
data.columns.forEach(column =>
|
||||||
|
{
|
||||||
|
column.search.search = "";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#battery-filter").on("change", function()
|
||||||
|
{
|
||||||
|
var value = $(this).val();
|
||||||
|
var text = $("#battery-filter option:selected").text();
|
||||||
|
if (value === "all")
|
||||||
|
{
|
||||||
|
text = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
batteriesJournalTable.column(1).search(text).draw();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#search").on("keyup", function()
|
||||||
|
{
|
||||||
|
var value = $(this).val();
|
||||||
|
if (value === "all")
|
||||||
|
{
|
||||||
|
value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
batteriesJournalTable.search(value).draw();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof GetUriParam("battery") !== "undefined")
|
||||||
|
{
|
||||||
|
$("#battery-filter").val(GetUriParam("battery"));
|
||||||
|
$("#battery-filter").trigger("change");
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).on('click', '.undo-battery-execution-button', function(e)
|
||||||
|
{
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var element = $(e.currentTarget);
|
||||||
|
var chargeCycleId = $(e.currentTarget).attr('data-charge-cycle-id');
|
||||||
|
|
||||||
|
Grocy.Api.Get('batteries/undo-charge-cycle/' + chargeCycleId.toString(),
|
||||||
|
function(result)
|
||||||
|
{
|
||||||
|
element.closest("tr").addClass("text-muted");
|
||||||
|
element.closest(".undo-battery-execution-button").addClass("disabled");
|
||||||
|
toastr.success(L("Charge cycle successfully undone"));
|
||||||
|
},
|
||||||
|
function(xhr)
|
||||||
|
{
|
||||||
|
console.error(xhr);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
@@ -10,7 +10,7 @@
|
|||||||
Grocy.Api.Get('batteries/track-charge-cycle/' + jsonForm.battery_id + '?tracked_time=' + $('#tracked_time').find('input').val(),
|
Grocy.Api.Get('batteries/track-charge-cycle/' + jsonForm.battery_id + '?tracked_time=' + $('#tracked_time').find('input').val(),
|
||||||
function(result)
|
function(result)
|
||||||
{
|
{
|
||||||
toastr.success(L('Tracked charge cylce of battery #1 on #2', batteryDetails.battery.name, $('#tracked_time').find('input').val()));
|
toastr.success(L('Tracked charge cycle of battery #1 on #2', batteryDetails.battery.name, $('#tracked_time').find('input').val()) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoChargeCycle(' + result.charge_cycle_id + ')"><i class="fas fa-undo"></i> ' + L("Undo") + '</a>');
|
||||||
|
|
||||||
$('#battery_id').val('');
|
$('#battery_id').val('');
|
||||||
$('#battery_id_text_input').focus();
|
$('#battery_id_text_input').focus();
|
||||||
@@ -86,3 +86,16 @@ $('#tracked_time').find('input').on('keypress', function (e)
|
|||||||
Grocy.FrontendHelpers.ValidateForm('batterytracking-form');
|
Grocy.FrontendHelpers.ValidateForm('batterytracking-form');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function UndoChargeCycle(chargeCycleId)
|
||||||
|
{
|
||||||
|
Grocy.Api.Get('batteries/undo-charge-cycle/' + chargeCycleId.toString(),
|
||||||
|
function(result)
|
||||||
|
{
|
||||||
|
toastr.success(L("Charge cycle successfully undone"));
|
||||||
|
},
|
||||||
|
function(xhr)
|
||||||
|
{
|
||||||
|
console.error(xhr);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@@ -1,46 +0,0 @@
|
|||||||
var choresAnalysisTable = $('#chores-analysis-table').DataTable({
|
|
||||||
'paginate': false,
|
|
||||||
'order': [[1, 'desc']],
|
|
||||||
'language': JSON.parse(L('datatables_localization')),
|
|
||||||
'scrollY': false,
|
|
||||||
'colReorder': true,
|
|
||||||
'stateSave': true,
|
|
||||||
'stateSaveParams': function(settings, data)
|
|
||||||
{
|
|
||||||
data.search.search = "";
|
|
||||||
|
|
||||||
data.columns.forEach(column =>
|
|
||||||
{
|
|
||||||
column.search.search = "";
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#chore-filter").on("change", function()
|
|
||||||
{
|
|
||||||
var value = $(this).val();
|
|
||||||
var text = $("#chore-filter option:selected").text();
|
|
||||||
if (value === "all")
|
|
||||||
{
|
|
||||||
text = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
choresAnalysisTable.column(0).search(text).draw();
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#search").on("keyup", function()
|
|
||||||
{
|
|
||||||
var value = $(this).val();
|
|
||||||
if (value === "all")
|
|
||||||
{
|
|
||||||
value = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
choresAnalysisTable.search(value).draw();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (typeof GetUriParam("chore") !== "undefined")
|
|
||||||
{
|
|
||||||
$("#chore-filter").val(GetUriParam("chore"));
|
|
||||||
$("#chore-filter").trigger("change");
|
|
||||||
}
|
|
70
public/viewjs/choresjournal.js
Normal file
70
public/viewjs/choresjournal.js
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
var choresJournalTable = $('#chores-journal-table').DataTable({
|
||||||
|
'paginate': true,
|
||||||
|
'order': [[1, 'desc']],
|
||||||
|
'columnDefs': [
|
||||||
|
{ 'orderable': false, 'targets': 0 }
|
||||||
|
],
|
||||||
|
'language': JSON.parse(L('datatables_localization')),
|
||||||
|
'scrollY': false,
|
||||||
|
'colReorder': true,
|
||||||
|
'stateSave': true,
|
||||||
|
'stateSaveParams': function(settings, data)
|
||||||
|
{
|
||||||
|
data.search.search = "";
|
||||||
|
|
||||||
|
data.columns.forEach(column =>
|
||||||
|
{
|
||||||
|
column.search.search = "";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#chore-filter").on("change", function()
|
||||||
|
{
|
||||||
|
var value = $(this).val();
|
||||||
|
var text = $("#chore-filter option:selected").text();
|
||||||
|
if (value === "all")
|
||||||
|
{
|
||||||
|
text = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
choresJournalTable.column(1).search(text).draw();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#search").on("keyup", function()
|
||||||
|
{
|
||||||
|
var value = $(this).val();
|
||||||
|
if (value === "all")
|
||||||
|
{
|
||||||
|
value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
choresJournalTable.search(value).draw();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof GetUriParam("chore") !== "undefined")
|
||||||
|
{
|
||||||
|
$("#chore-filter").val(GetUriParam("chore"));
|
||||||
|
$("#chore-filter").trigger("change");
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).on('click', '.undo-chore-execution-button', function(e)
|
||||||
|
{
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var element = $(e.currentTarget);
|
||||||
|
var executionId = $(e.currentTarget).attr('data-execution-id');
|
||||||
|
|
||||||
|
Grocy.Api.Get('chores/undo-chore-execution/' + executionId.toString(),
|
||||||
|
function(result)
|
||||||
|
{
|
||||||
|
element.closest("tr").addClass("text-muted");
|
||||||
|
element.closest(".undo-chore-execution-button").addClass("disabled");
|
||||||
|
toastr.success(L("Chore execution successfully undone"));
|
||||||
|
},
|
||||||
|
function(xhr)
|
||||||
|
{
|
||||||
|
console.error(xhr);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
@@ -10,7 +10,7 @@
|
|||||||
Grocy.Api.Get('chores/track-chore-execution/' + jsonForm.chore_id + '?tracked_time=' + Grocy.Components.DateTimePicker.GetValue() + "&done_by=" + Grocy.Components.UserPicker.GetValue(),
|
Grocy.Api.Get('chores/track-chore-execution/' + jsonForm.chore_id + '?tracked_time=' + Grocy.Components.DateTimePicker.GetValue() + "&done_by=" + Grocy.Components.UserPicker.GetValue(),
|
||||||
function(result)
|
function(result)
|
||||||
{
|
{
|
||||||
toastr.success(L('Tracked execution of chore #1 on #2', choreDetails.chore.name, Grocy.Components.DateTimePicker.GetValue()));
|
toastr.success(L('Tracked execution of chore #1 on #2', choreDetails.chore.name, Grocy.Components.DateTimePicker.GetValue()) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoChoreExecution(' + result.chore_execution_id + ')"><i class="fas fa-undo"></i> ' + L("Undo") + '</a>');
|
||||||
|
|
||||||
$('#chore_id').val('');
|
$('#chore_id').val('');
|
||||||
$('#chore_id_text_input').focus();
|
$('#chore_id_text_input').focus();
|
||||||
@@ -82,3 +82,17 @@ Grocy.Components.DateTimePicker.GetInputElement().on('keypress', function(e)
|
|||||||
{
|
{
|
||||||
Grocy.FrontendHelpers.ValidateForm('choretracking-form');
|
Grocy.FrontendHelpers.ValidateForm('choretracking-form');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function UndoChoreExecution(executionId)
|
||||||
|
{
|
||||||
|
Grocy.Api.Get('chores/undo-chore-execution/' + executionId.toString(),
|
||||||
|
function(result)
|
||||||
|
{
|
||||||
|
toastr.success(L("Chore execution successfully undone"));
|
||||||
|
},
|
||||||
|
function(xhr)
|
||||||
|
{
|
||||||
|
console.error(xhr);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@@ -11,6 +11,9 @@ Grocy.Components.BatteryCard.Refresh = function(batteryId)
|
|||||||
$('#batterycard-battery-last-charged-timeago').text($.timeago(batteryDetails.last_charged || ''));
|
$('#batterycard-battery-last-charged-timeago').text($.timeago(batteryDetails.last_charged || ''));
|
||||||
$('#batterycard-battery-charge-cycles-count').text((batteryDetails.charge_cycles_count || '0'));
|
$('#batterycard-battery-charge-cycles-count').text((batteryDetails.charge_cycles_count || '0'));
|
||||||
|
|
||||||
|
$('#batterycard-battery-edit-button').attr("href", U("/battery/" + batteryDetails.battery.id.toString()));
|
||||||
|
$('#batterycard-battery-edit-button').removeClass("disabled");
|
||||||
|
|
||||||
EmptyElementWhenMatches('#batterycard-battery-last-charged-timeago', L('timeago_nan'));
|
EmptyElementWhenMatches('#batterycard-battery-last-charged-timeago', L('timeago_nan'));
|
||||||
},
|
},
|
||||||
function(xhr)
|
function(xhr)
|
||||||
|
@@ -11,6 +11,9 @@ Grocy.Components.ChoreCard.Refresh = function(choreId)
|
|||||||
$('#chorecard-chore-tracked-count').text((choreDetails.tracked_count || '0'));
|
$('#chorecard-chore-tracked-count').text((choreDetails.tracked_count || '0'));
|
||||||
$('#chorecard-chore-last-done-by').text((choreDetails.last_done_by.display_name || L('Unknown')));
|
$('#chorecard-chore-last-done-by').text((choreDetails.last_done_by.display_name || L('Unknown')));
|
||||||
|
|
||||||
|
$('#chorecard-chore-edit-button').attr("href", U("/chore/" + choreDetails.chore.id.toString()));
|
||||||
|
$('#chorecard-chore-edit-button').removeClass("disabled");
|
||||||
|
|
||||||
EmptyElementWhenMatches('#chorecard-chore-last-tracked-timeago', L('timeago_nan'));
|
EmptyElementWhenMatches('#chorecard-chore-last-tracked-timeago', L('timeago_nan'));
|
||||||
},
|
},
|
||||||
function(xhr)
|
function(xhr)
|
||||||
|
@@ -24,6 +24,23 @@ Grocy.Components.DateTimePicker.SetValue = function(value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Grocy.Components.DateTimePicker.Clear = function()
|
||||||
|
{
|
||||||
|
$(".datetimepicker").datetimepicker("destroy");
|
||||||
|
Grocy.Components.DateTimePicker.Init();
|
||||||
|
|
||||||
|
Grocy.Components.DateTimePicker.GetInputElement().val("");
|
||||||
|
|
||||||
|
// "Click" the shortcut checkbox when the desired value is
|
||||||
|
// not the shortcut value and it is currently set
|
||||||
|
value = "";
|
||||||
|
var shortcutValue = $("#datetimepicker-shortcut").data("datetimepicker-shortcut-value");
|
||||||
|
if (value != shortcutValue && $("#datetimepicker-shortcut").is(":checked"))
|
||||||
|
{
|
||||||
|
$("#datetimepicker-shortcut").click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var startDate = null;
|
var startDate = null;
|
||||||
if (Grocy.Components.DateTimePicker.GetInputElement().data('init-with-now') === true)
|
if (Grocy.Components.DateTimePicker.GetInputElement().data('init-with-now') === true)
|
||||||
{
|
{
|
||||||
@@ -40,46 +57,50 @@ if (Grocy.Components.DateTimePicker.GetInputElement().data('limit-end-to-now') =
|
|||||||
limitDate = moment();
|
limitDate = moment();
|
||||||
}
|
}
|
||||||
|
|
||||||
$('.datetimepicker').datetimepicker(
|
Grocy.Components.DateTimePicker.Init = function()
|
||||||
{
|
{
|
||||||
format: Grocy.Components.DateTimePicker.GetInputElement().data('format'),
|
$('.datetimepicker').datetimepicker(
|
||||||
buttons: {
|
{
|
||||||
showToday: true,
|
format: Grocy.Components.DateTimePicker.GetInputElement().data('format'),
|
||||||
showClose: true
|
buttons: {
|
||||||
},
|
showToday: true,
|
||||||
calendarWeeks: true,
|
showClose: true
|
||||||
maxDate: limitDate,
|
},
|
||||||
locale: moment.locale(),
|
calendarWeeks: true,
|
||||||
defaultDate: startDate,
|
maxDate: limitDate,
|
||||||
useCurrent: false,
|
locale: moment.locale(),
|
||||||
icons: {
|
defaultDate: startDate,
|
||||||
time: 'far fa-clock',
|
useCurrent: false,
|
||||||
date: 'far fa-calendar',
|
icons: {
|
||||||
up: 'fas fa-arrow-up',
|
time: 'far fa-clock',
|
||||||
down: 'fas fa-arrow-down',
|
date: 'far fa-calendar',
|
||||||
previous: 'fas fa-chevron-left',
|
up: 'fas fa-arrow-up',
|
||||||
next: 'fas fa-chevron-right',
|
down: 'fas fa-arrow-down',
|
||||||
today: 'fas fa-calendar-check',
|
previous: 'fas fa-chevron-left',
|
||||||
clear: 'far fa-trash-alt',
|
next: 'fas fa-chevron-right',
|
||||||
close: 'far fa-times-circle'
|
today: 'fas fa-calendar-check',
|
||||||
},
|
clear: 'far fa-trash-alt',
|
||||||
sideBySide: true,
|
close: 'far fa-times-circle'
|
||||||
keyBinds: {
|
},
|
||||||
up: function(widget) { },
|
sideBySide: true,
|
||||||
down: function(widget) { },
|
keyBinds: {
|
||||||
'control up': function(widget) { },
|
up: function(widget) { },
|
||||||
'control down': function(widget) { },
|
down: function(widget) { },
|
||||||
left: function(widget) { },
|
'control up': function(widget) { },
|
||||||
right: function(widget) { },
|
'control down': function(widget) { },
|
||||||
pageUp: function(widget) { },
|
left: function(widget) { },
|
||||||
pageDown: function(widget) { },
|
right: function(widget) { },
|
||||||
enter: function(widget) { },
|
pageUp: function(widget) { },
|
||||||
escape: function(widget) { },
|
pageDown: function(widget) { },
|
||||||
'control space': function(widget) { },
|
enter: function(widget) { },
|
||||||
t: function(widget) { },
|
escape: function(widget) { },
|
||||||
'delete': function(widget) { }
|
'control space': function(widget) { },
|
||||||
}
|
t: function(widget) { },
|
||||||
});
|
'delete': function(widget) { }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Grocy.Components.DateTimePicker.Init();
|
||||||
|
|
||||||
Grocy.Components.DateTimePicker.GetInputElement().on('keyup', function(e)
|
Grocy.Components.DateTimePicker.GetInputElement().on('keyup', function(e)
|
||||||
{
|
{
|
||||||
|
@@ -15,6 +15,9 @@ Grocy.Components.ProductCard.Refresh = function(productId)
|
|||||||
$('#productcard-product-last-used').text((productDetails.last_used || L('never')).substring(0, 10));
|
$('#productcard-product-last-used').text((productDetails.last_used || L('never')).substring(0, 10));
|
||||||
$('#productcard-product-last-used-timeago').text($.timeago(productDetails.last_used || ''));
|
$('#productcard-product-last-used-timeago').text($.timeago(productDetails.last_used || ''));
|
||||||
|
|
||||||
|
$('#productcard-product-edit-button').attr("href", U("/product/" + productDetails.product.id.toString()));
|
||||||
|
$('#productcard-product-edit-button').removeClass("disabled");
|
||||||
|
|
||||||
if (productDetails.last_price !== null)
|
if (productDetails.last_price !== null)
|
||||||
{
|
{
|
||||||
$('#productcard-product-last-price').text(Number.parseFloat(productDetails.last_price).toLocaleString() + ' ' + Grocy.Currency);
|
$('#productcard-product-last-price').text(Number.parseFloat(productDetails.last_price).toLocaleString() + ' ' + Grocy.Currency);
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
Grocy.Api.Get('stock/consume-product/' + jsonForm.product_id + '/' + jsonForm.amount + '?spoiled=' + spoiled,
|
Grocy.Api.Get('stock/consume-product/' + jsonForm.product_id + '/' + jsonForm.amount + '?spoiled=' + spoiled,
|
||||||
function(result)
|
function(result)
|
||||||
{
|
{
|
||||||
toastr.success(L('Removed #1 #2 of #3 from stock', jsonForm.amount, productDetails.quantity_unit_stock.name, productDetails.product.name));
|
toastr.success(L('Removed #1 #2 of #3 from stock', jsonForm.amount, Pluralize(jsonForm.amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural), productDetails.product.name) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoStockBooking(' + result.booking_id + ')"><i class="fas fa-undo"></i> ' + L("Undo") + '</a>');
|
||||||
|
|
||||||
$('#amount').val(1);
|
$('#amount').val(1);
|
||||||
Grocy.Components.ProductPicker.SetValue('');
|
Grocy.Components.ProductPicker.SetValue('');
|
||||||
@@ -102,3 +102,17 @@ $('#consume-form input').keydown(function(event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function UndoStockBooking(bookingId)
|
||||||
|
{
|
||||||
|
Grocy.Api.Get('stock/undo-booking/' + bookingId.toString(),
|
||||||
|
function(result)
|
||||||
|
{
|
||||||
|
toastr.success(L("Booking successfully undone"));
|
||||||
|
},
|
||||||
|
function(xhr)
|
||||||
|
{
|
||||||
|
console.error(xhr);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@@ -116,7 +116,7 @@ $("#selectedEquipmentInstructionManualToggleFullscreenButton").on('click', funct
|
|||||||
$("#selectedEquipmentInstructionManualCard").toggleClass("fullscreen");
|
$("#selectedEquipmentInstructionManualCard").toggleClass("fullscreen");
|
||||||
$("#selectedEquipmentInstructionManualCard .card-header").toggleClass("fixed-top");
|
$("#selectedEquipmentInstructionManualCard .card-header").toggleClass("fixed-top");
|
||||||
$("#selectedEquipmentInstructionManualCard .card-body").toggleClass("mt-5");
|
$("#selectedEquipmentInstructionManualCard .card-body").toggleClass("mt-5");
|
||||||
$("body").toggleClass("fullscreen-responsive-embed-active");
|
$("body").toggleClass("fullscreen-card");
|
||||||
ResizeResponsiveEmbeds(true);
|
ResizeResponsiveEmbeds(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -32,7 +32,7 @@
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
toastr.success(L('Stock amount of #1 is now #2 #3', productDetails.product.name, jsonForm.new_amount, productDetails.quantity_unit_stock.name));
|
toastr.success(L('Stock amount of #1 is now #2 #3', productDetails.product.name, jsonForm.new_amount, Pluralize(jsonForm.new_amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural)) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoStockBooking(' + result.booking_id + ')"><i class="fas fa-undo"></i> ' + L("Undo") + '</a>');
|
||||||
|
|
||||||
if (addBarcode !== undefined)
|
if (addBarcode !== undefined)
|
||||||
{
|
{
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
{
|
{
|
||||||
$('#inventory-change-info').addClass('d-none');
|
$('#inventory-change-info').addClass('d-none');
|
||||||
$('#new_amount').val('');
|
$('#new_amount').val('');
|
||||||
Grocy.Components.DateTimePicker.SetValue('');
|
Grocy.Components.DateTimePicker.Clear();
|
||||||
Grocy.Components.ProductPicker.SetValue('');
|
Grocy.Components.ProductPicker.SetValue('');
|
||||||
Grocy.Components.ProductPicker.GetInputElement().focus();
|
Grocy.Components.ProductPicker.GetInputElement().focus();
|
||||||
Grocy.FrontendHelpers.ValidateForm('inventory-form');
|
Grocy.FrontendHelpers.ValidateForm('inventory-form');
|
||||||
@@ -186,3 +186,17 @@ $('#new_amount').on('keyup', function(e)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function UndoStockBooking(bookingId)
|
||||||
|
{
|
||||||
|
Grocy.Api.Get('stock/undo-booking/' + bookingId.toString(),
|
||||||
|
function(result)
|
||||||
|
{
|
||||||
|
toastr.success(L("Booking successfully undone"));
|
||||||
|
},
|
||||||
|
function(xhr)
|
||||||
|
{
|
||||||
|
console.error(xhr);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@@ -196,6 +196,24 @@ $('#delete-current-product-picture-button').on('click', function (e)
|
|||||||
$("#delete-current-product-picture-button").addClass("disabled");
|
$("#delete-current-product-picture-button").addClass("disabled");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (Grocy.EditMode === 'create')
|
||||||
|
{
|
||||||
|
if (Grocy.UserSettings.product_presets_location_id.toString() !== '-1')
|
||||||
|
{
|
||||||
|
$("#location_id").val(Grocy.UserSettings.product_presets_location_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Grocy.UserSettings.product_presets_product_group_id.toString() !== '-1')
|
||||||
|
{
|
||||||
|
$("#product_group_id").val(Grocy.UserSettings.product_presets_product_group_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Grocy.UserSettings.product_presets_qu_id.toString() !== '-1')
|
||||||
|
{
|
||||||
|
$("select.input-group-qu").val(Grocy.UserSettings.product_presets_qu_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$('#name').focus();
|
$('#name').focus();
|
||||||
$('.input-group-qu').trigger('change');
|
$('.input-group-qu').trigger('change');
|
||||||
Grocy.FrontendHelpers.ValidateForm('product-form');
|
Grocy.FrontendHelpers.ValidateForm('product-form');
|
||||||
|
3
public/viewjs/productpresets.js
Normal file
3
public/viewjs/productpresets.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
$("#product_presets_location_id").val(Grocy.UserSettings.product_presets_location_id);
|
||||||
|
$("#product_presets_product_group_id").val(Grocy.UserSettings.product_presets_product_group_id);
|
||||||
|
$("#product_presets_qu_id").val(Grocy.UserSettings.product_presets_qu_id);
|
@@ -5,7 +5,7 @@
|
|||||||
var jsonForm = $('#purchase-form').serializeJSON();
|
var jsonForm = $('#purchase-form').serializeJSON();
|
||||||
|
|
||||||
Grocy.Api.Get('stock/get-product-details/' + jsonForm.product_id,
|
Grocy.Api.Get('stock/get-product-details/' + jsonForm.product_id,
|
||||||
function (productDetails)
|
function(productDetails)
|
||||||
{
|
{
|
||||||
var amount = jsonForm.amount * productDetails.product.qu_factor_purchase_to_stock;
|
var amount = jsonForm.amount * productDetails.product.qu_factor_purchase_to_stock;
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
toastr.success(L('Added #1 #2 of #3 to stock', amount, productDetails.quantity_unit_stock.name, productDetails.product.name));
|
toastr.success(L('Added #1 #2 of #3 to stock', amount, Pluralize(amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural), productDetails.product.name) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoStockBooking(' + result.booking_id + ')"><i class="fas fa-undo"></i> ' + L("Undo") + '</a>');
|
||||||
|
|
||||||
if (addBarcode !== undefined)
|
if (addBarcode !== undefined)
|
||||||
{
|
{
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
{
|
{
|
||||||
$('#amount').val(0);
|
$('#amount').val(0);
|
||||||
$('#price').val('');
|
$('#price').val('');
|
||||||
Grocy.Components.DateTimePicker.SetValue('');
|
Grocy.Components.DateTimePicker.Clear();
|
||||||
Grocy.Components.ProductPicker.SetValue('');
|
Grocy.Components.ProductPicker.SetValue('');
|
||||||
Grocy.Components.ProductPicker.GetInputElement().focus();
|
Grocy.Components.ProductPicker.GetInputElement().focus();
|
||||||
Grocy.FrontendHelpers.ValidateForm('purchase-form');
|
Grocy.FrontendHelpers.ValidateForm('purchase-form');
|
||||||
@@ -171,3 +171,17 @@ $('#amount').on('change', function (e)
|
|||||||
{
|
{
|
||||||
Grocy.FrontendHelpers.ValidateForm('purchase-form');
|
Grocy.FrontendHelpers.ValidateForm('purchase-form');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function UndoStockBooking(bookingId)
|
||||||
|
{
|
||||||
|
Grocy.Api.Get('stock/undo-booking/' + bookingId.toString(),
|
||||||
|
function(result)
|
||||||
|
{
|
||||||
|
toastr.success(L("Booking successfully undone"));
|
||||||
|
},
|
||||||
|
function(xhr)
|
||||||
|
{
|
||||||
|
console.error(xhr);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@@ -17,8 +17,10 @@
|
|||||||
var recipesPosTables = $('#recipes-pos-table').DataTable({
|
var recipesPosTables = $('#recipes-pos-table').DataTable({
|
||||||
'paginate': false,
|
'paginate': false,
|
||||||
'order': [[1, 'asc']],
|
'order': [[1, 'asc']],
|
||||||
|
"orderFixed": [[4, 'asc']],
|
||||||
'columnDefs': [
|
'columnDefs': [
|
||||||
{ 'orderable': false, 'targets': 0 }
|
{ 'orderable': false, 'targets': 0 },
|
||||||
|
{ 'visible': false, 'targets': 4 }
|
||||||
],
|
],
|
||||||
'language': JSON.parse(L('datatables_localization')),
|
'language': JSON.parse(L('datatables_localization')),
|
||||||
'scrollY': false,
|
'scrollY': false,
|
||||||
@@ -32,18 +34,31 @@ var recipesPosTables = $('#recipes-pos-table').DataTable({
|
|||||||
{
|
{
|
||||||
column.search.search = "";
|
column.search.search = "";
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
'rowGroup': {
|
||||||
|
dataSrc: 4
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#search").on("keyup", function ()
|
var recipesIncludesTables = $('#recipes-includes-table').DataTable({
|
||||||
{
|
'paginate': false,
|
||||||
var value = $(this).val();
|
'order': [[1, 'asc']],
|
||||||
if (value === "all")
|
'columnDefs': [
|
||||||
|
{ 'orderable': false, 'targets': 0 }
|
||||||
|
],
|
||||||
|
'language': JSON.parse(L('datatables_localization')),
|
||||||
|
'scrollY': false,
|
||||||
|
'colReorder': true,
|
||||||
|
'stateSave': true,
|
||||||
|
'stateSaveParams': function (settings, data)
|
||||||
{
|
{
|
||||||
value = "";
|
data.search.search = "";
|
||||||
}
|
|
||||||
|
|
||||||
recipesPosTables.search(value).draw();
|
data.columns.forEach(column =>
|
||||||
|
{
|
||||||
|
column.search.search = "";
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Grocy.FrontendHelpers.ValidateForm('recipe-form');
|
Grocy.FrontendHelpers.ValidateForm('recipe-form');
|
||||||
@@ -108,6 +123,43 @@ $(document).on('click', '.recipe-pos-delete-button', function(e)
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(document).on('click', '.recipe-include-delete-button', function(e)
|
||||||
|
{
|
||||||
|
var objectName = $(e.currentTarget).attr('data-recipe-include-name');
|
||||||
|
var objectId = $(e.currentTarget).attr('data-recipe-include-id');
|
||||||
|
|
||||||
|
bootbox.confirm({
|
||||||
|
message: L('Are you sure to remove included recipe "#1"?', objectName),
|
||||||
|
buttons: {
|
||||||
|
confirm: {
|
||||||
|
label: L('Yes'),
|
||||||
|
className: 'btn-success'
|
||||||
|
},
|
||||||
|
cancel: {
|
||||||
|
label: L('No'),
|
||||||
|
className: 'btn-danger'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
callback: function(result)
|
||||||
|
{
|
||||||
|
if (result === true)
|
||||||
|
{
|
||||||
|
Grocy.Api.Post('edit-object/recipes/' + Grocy.EditObjectId, $('#recipe-form').serializeJSON(), function() { }, function() { });
|
||||||
|
Grocy.Api.Get('delete-object/recipes_nestings/' + objectId,
|
||||||
|
function(result)
|
||||||
|
{
|
||||||
|
window.location.href = U('/recipe/' + Grocy.EditObjectId);
|
||||||
|
},
|
||||||
|
function(xhr)
|
||||||
|
{
|
||||||
|
console.error(xhr);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
$(document).on('click', '.recipe-pos-order-missing-button', function(e)
|
$(document).on('click', '.recipe-pos-order-missing-button', function(e)
|
||||||
{
|
{
|
||||||
var productName = $(e.currentTarget).attr('data-product-name');
|
var productName = $(e.currentTarget).attr('data-product-name');
|
||||||
@@ -156,6 +208,28 @@ $(document).on('click', '.recipe-pos-edit-button', function (e)
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(document).on('click', '.recipe-include-edit-button', function (e)
|
||||||
|
{
|
||||||
|
var id = $(e.currentTarget).attr('data-recipe-include-id');
|
||||||
|
var recipeId = $(e.currentTarget).attr('data-recipe-included-recipe-id');
|
||||||
|
console.log(recipeId);
|
||||||
|
Grocy.Api.Post('edit-object/recipes/' + Grocy.EditObjectId, $('#recipe-form').serializeJSON(),
|
||||||
|
function(result)
|
||||||
|
{
|
||||||
|
$("#recipe-include-editform-title").text(L("Edit included recipe"));
|
||||||
|
$("#recipe-include-form").data("edit-mode", "edit");
|
||||||
|
$("#recipe-include-form").data("recipe-nesting-id", id);
|
||||||
|
$("#includes_recipe_id").val(recipeId);
|
||||||
|
$("#recipe-include-editform-modal").modal("show");
|
||||||
|
Grocy.FrontendHelpers.ValidateForm("recipe-include-form");
|
||||||
|
},
|
||||||
|
function(xhr)
|
||||||
|
{
|
||||||
|
console.error(xhr);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
$("#recipe-pos-add-button").on("click", function(e)
|
$("#recipe-pos-add-button").on("click", function(e)
|
||||||
{
|
{
|
||||||
Grocy.Api.Post('edit-object/recipes/' + Grocy.EditObjectId, $('#recipe-form').serializeJSON(),
|
Grocy.Api.Post('edit-object/recipes/' + Grocy.EditObjectId, $('#recipe-form').serializeJSON(),
|
||||||
@@ -170,6 +244,62 @@ $("#recipe-pos-add-button").on("click", function(e)
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#recipe-include-add-button").on("click", function(e)
|
||||||
|
{
|
||||||
|
Grocy.Api.Post('edit-object/recipes/' + Grocy.EditObjectId, $('#recipe-form').serializeJSON(),
|
||||||
|
function(result)
|
||||||
|
{
|
||||||
|
$("#recipe-include-editform-title").text(L("Add included recipe"));
|
||||||
|
$("#recipe-include-form").data("edit-mode", "create");
|
||||||
|
$("#includes_recipe_id").val("");
|
||||||
|
$("#recipe-include-editform-modal").modal("show");
|
||||||
|
Grocy.FrontendHelpers.ValidateForm("recipe-include-form");
|
||||||
|
},
|
||||||
|
function(xhr)
|
||||||
|
{
|
||||||
|
console.error(xhr);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#save-recipe-include-button').on('click', function(e)
|
||||||
|
{
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var nestingId = $("#recipe-include-form").data("recipe-nesting-id");
|
||||||
|
var editMode = $("#recipe-include-form").data("edit-mode");
|
||||||
|
|
||||||
|
var jsonData = $('#recipe-include-form').serializeJSON();
|
||||||
|
jsonData.recipe_id = Grocy.EditObjectId;
|
||||||
|
|
||||||
|
if (editMode === 'create')
|
||||||
|
{
|
||||||
|
Grocy.Api.Post('add-object/recipes_nestings', jsonData,
|
||||||
|
function(result)
|
||||||
|
{
|
||||||
|
window.location.href = U('/recipe/' + Grocy.EditObjectId);
|
||||||
|
},
|
||||||
|
function(xhr)
|
||||||
|
{
|
||||||
|
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Grocy.Api.Post('edit-object/recipes_nestings/' + nestingId, jsonData,
|
||||||
|
function(result)
|
||||||
|
{
|
||||||
|
window.location.href = U('/recipe/' + Grocy.EditObjectId);
|
||||||
|
},
|
||||||
|
function(xhr)
|
||||||
|
{
|
||||||
|
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$('#description').summernote({
|
$('#description').summernote({
|
||||||
minHeight: '300px',
|
minHeight: '300px',
|
||||||
lang: L('summernote_locale')
|
lang: L('summernote_locale')
|
||||||
|
@@ -158,6 +158,7 @@ recipesTables.on('select', function(e, dt, type, indexes)
|
|||||||
$("#selectedRecipeToggleFullscreenButton").on('click', function(e)
|
$("#selectedRecipeToggleFullscreenButton").on('click', function(e)
|
||||||
{
|
{
|
||||||
$("#selectedRecipeCard").toggleClass("fullscreen");
|
$("#selectedRecipeCard").toggleClass("fullscreen");
|
||||||
|
$("body").toggleClass("fullscreen-card");
|
||||||
$("#selectedRecipeCard .card-header").toggleClass("fixed-top");
|
$("#selectedRecipeCard .card-header").toggleClass("fixed-top");
|
||||||
$("#selectedRecipeCard .card-body").toggleClass("mt-5");
|
$("#selectedRecipeCard .card-body").toggleClass("mt-5");
|
||||||
});
|
});
|
||||||
|
70
public/viewjs/stockjournal.js
Normal file
70
public/viewjs/stockjournal.js
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
var stockJournalTable = $('#stock-journal-table').DataTable({
|
||||||
|
'paginate': true,
|
||||||
|
'order': [[3, 'desc']],
|
||||||
|
'columnDefs': [
|
||||||
|
{ 'orderable': false, 'targets': 0 }
|
||||||
|
],
|
||||||
|
'language': JSON.parse(L('datatables_localization')),
|
||||||
|
'scrollY': false,
|
||||||
|
'colReorder': true,
|
||||||
|
'stateSave': true,
|
||||||
|
'stateSaveParams': function(settings, data)
|
||||||
|
{
|
||||||
|
data.search.search = "";
|
||||||
|
|
||||||
|
data.columns.forEach(column =>
|
||||||
|
{
|
||||||
|
column.search.search = "";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#product-filter").on("change", function()
|
||||||
|
{
|
||||||
|
var value = $(this).val();
|
||||||
|
var text = $("#product-filter option:selected").text();
|
||||||
|
if (value === "all")
|
||||||
|
{
|
||||||
|
text = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
stockJournalTable.column(1).search(text).draw();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#search").on("keyup", function()
|
||||||
|
{
|
||||||
|
var value = $(this).val();
|
||||||
|
if (value === "all")
|
||||||
|
{
|
||||||
|
value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
stockJournalTable.search(value).draw();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof GetUriParam("product") !== "undefined")
|
||||||
|
{
|
||||||
|
$("#product-filter").val(GetUriParam("product"));
|
||||||
|
$("#product-filter").trigger("change");
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).on('click', '.undo-stock-booking-button', function(e)
|
||||||
|
{
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var element = $(e.currentTarget);
|
||||||
|
var bookingId = $(e.currentTarget).attr('data-booking-id');
|
||||||
|
|
||||||
|
Grocy.Api.Get('stock/undo-booking/' + bookingId.toString(),
|
||||||
|
function(result)
|
||||||
|
{
|
||||||
|
element.closest("tr").addClass("text-muted");
|
||||||
|
element.closest(".undo-stock-booking-button").addClass("disabled");
|
||||||
|
toastr.success(L("Booking successfully undone"));
|
||||||
|
},
|
||||||
|
function(xhr)
|
||||||
|
{
|
||||||
|
console.error(xhr);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
@@ -31,6 +31,17 @@ $("#location-filter").on("change", function()
|
|||||||
stockOverviewTable.column(4).search(value).draw();
|
stockOverviewTable.column(4).search(value).draw();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#product-group-filter").on("change", function()
|
||||||
|
{
|
||||||
|
var value = $(this).val();
|
||||||
|
if (value === "all")
|
||||||
|
{
|
||||||
|
value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
stockOverviewTable.column(6).search(value).draw();
|
||||||
|
});
|
||||||
|
|
||||||
$("#status-filter").on("change", function()
|
$("#status-filter").on("change", function()
|
||||||
{
|
{
|
||||||
var value = $(this).val();
|
var value = $(this).val();
|
||||||
@@ -143,41 +154,8 @@ $(document).on('click', '.product-consume-button', function(e)
|
|||||||
|
|
||||||
$(document).on("click", ".product-name-cell", function(e)
|
$(document).on("click", ".product-name-cell", function(e)
|
||||||
{
|
{
|
||||||
var productHasPicture = BoolVal($(e.currentTarget).attr("data-product-has-picture"));
|
Grocy.Components.ProductCard.Refresh($(e.currentTarget).attr("data-product-id"));
|
||||||
|
$("#stockoverview-productcard-modal").modal("show");
|
||||||
if (productHasPicture)
|
|
||||||
{
|
|
||||||
var pictureUrl = $(e.currentTarget).attr("data-picture-url");
|
|
||||||
var productName = $(e.currentTarget).attr("data-product-name");
|
|
||||||
var productId = $(e.currentTarget).attr("data-product-id");
|
|
||||||
|
|
||||||
bootbox.dialog({
|
|
||||||
title: L("Image of product #1", productName),
|
|
||||||
message: "<img src='" + pictureUrl + "' class='img-fluid img-thumbnail'>",
|
|
||||||
backdrop: false,
|
|
||||||
onEscape: true,
|
|
||||||
closeButton: false,
|
|
||||||
className: 'centered-dialog',
|
|
||||||
buttons: {
|
|
||||||
editproduct: {
|
|
||||||
label: '<i class="fas fa-edit"></i> ' + L('Edit product'),
|
|
||||||
className: 'btn-info responsive-button',
|
|
||||||
callback: function ()
|
|
||||||
{
|
|
||||||
window.location.href = U('/product/' + productId + '?returnto=' + encodeURIComponent(window.location.pathname) + '#product-picture');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
close: {
|
|
||||||
label: L('Close'),
|
|
||||||
className: 'btn-default responsive-button',
|
|
||||||
callback: function()
|
|
||||||
{
|
|
||||||
bootbox.hideAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function RefreshStatistics()
|
function RefreshStatistics()
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 129 KiB |
Binary file not shown.
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 106 KiB |
Binary file not shown.
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 166 KiB |
@@ -26,6 +26,7 @@ $app->group('', function()
|
|||||||
$this->get('/inventory', '\Grocy\Controllers\StockController:Inventory');
|
$this->get('/inventory', '\Grocy\Controllers\StockController:Inventory');
|
||||||
$this->get('/products', '\Grocy\Controllers\StockController:ProductsList');
|
$this->get('/products', '\Grocy\Controllers\StockController:ProductsList');
|
||||||
$this->get('/product/{productId}', '\Grocy\Controllers\StockController:ProductEditForm');
|
$this->get('/product/{productId}', '\Grocy\Controllers\StockController:ProductEditForm');
|
||||||
|
$this->get('/productpresets', '\Grocy\Controllers\StockController:ProductDefaults');
|
||||||
$this->get('/locations', '\Grocy\Controllers\StockController:LocationsList');
|
$this->get('/locations', '\Grocy\Controllers\StockController:LocationsList');
|
||||||
$this->get('/location/{locationId}', '\Grocy\Controllers\StockController:LocationEditForm');
|
$this->get('/location/{locationId}', '\Grocy\Controllers\StockController:LocationEditForm');
|
||||||
$this->get('/quantityunits', '\Grocy\Controllers\StockController:QuantityUnitsList');
|
$this->get('/quantityunits', '\Grocy\Controllers\StockController:QuantityUnitsList');
|
||||||
@@ -34,6 +35,7 @@ $app->group('', function()
|
|||||||
$this->get('/productgroup/{productGroupId}', '\Grocy\Controllers\StockController:ProductGroupEditForm');
|
$this->get('/productgroup/{productGroupId}', '\Grocy\Controllers\StockController:ProductGroupEditForm');
|
||||||
$this->get('/shoppinglist', '\Grocy\Controllers\StockController:ShoppingList');
|
$this->get('/shoppinglist', '\Grocy\Controllers\StockController:ShoppingList');
|
||||||
$this->get('/shoppinglistitem/{itemId}', '\Grocy\Controllers\StockController:ShoppingListItemEditForm');
|
$this->get('/shoppinglistitem/{itemId}', '\Grocy\Controllers\StockController:ShoppingListItemEditForm');
|
||||||
|
$this->get('/stockjournal', '\Grocy\Controllers\StockController:Journal');
|
||||||
|
|
||||||
// Recipe routes
|
// Recipe routes
|
||||||
$this->get('/recipes', '\Grocy\Controllers\RecipesController:Overview');
|
$this->get('/recipes', '\Grocy\Controllers\RecipesController:Overview');
|
||||||
@@ -43,7 +45,7 @@ $app->group('', function()
|
|||||||
// Chore routes
|
// Chore routes
|
||||||
$this->get('/choresoverview', '\Grocy\Controllers\ChoresController:Overview');
|
$this->get('/choresoverview', '\Grocy\Controllers\ChoresController:Overview');
|
||||||
$this->get('/choretracking', '\Grocy\Controllers\ChoresController:TrackChoreExecution');
|
$this->get('/choretracking', '\Grocy\Controllers\ChoresController:TrackChoreExecution');
|
||||||
$this->get('/choresanalysis', '\Grocy\Controllers\ChoresController:Analysis');
|
$this->get('/choresjournal', '\Grocy\Controllers\ChoresController:Journal');
|
||||||
|
|
||||||
$this->get('/chores', '\Grocy\Controllers\ChoresController:ChoresList');
|
$this->get('/chores', '\Grocy\Controllers\ChoresController:ChoresList');
|
||||||
$this->get('/chore/{choreId}', '\Grocy\Controllers\ChoresController:ChoreEditForm');
|
$this->get('/chore/{choreId}', '\Grocy\Controllers\ChoresController:ChoreEditForm');
|
||||||
@@ -51,6 +53,7 @@ $app->group('', function()
|
|||||||
// Battery routes
|
// Battery routes
|
||||||
$this->get('/batteriesoverview', '\Grocy\Controllers\BatteriesController:Overview');
|
$this->get('/batteriesoverview', '\Grocy\Controllers\BatteriesController:Overview');
|
||||||
$this->get('/batterytracking', '\Grocy\Controllers\BatteriesController:TrackChargeCycle');
|
$this->get('/batterytracking', '\Grocy\Controllers\BatteriesController:TrackChargeCycle');
|
||||||
|
$this->get('/batteriesjournal', '\Grocy\Controllers\BatteriesController:Journal');
|
||||||
|
|
||||||
$this->get('/batteries', '\Grocy\Controllers\BatteriesController:BatteriesList');
|
$this->get('/batteries', '\Grocy\Controllers\BatteriesController:BatteriesList');
|
||||||
$this->get('/battery/{batteryId}', '\Grocy\Controllers\BatteriesController:BatteryEditForm');
|
$this->get('/battery/{batteryId}', '\Grocy\Controllers\BatteriesController:BatteryEditForm');
|
||||||
@@ -113,6 +116,7 @@ $app->group('/api', function()
|
|||||||
$this->get('/stock/add-missing-products-to-shoppinglist', '\Grocy\Controllers\StockApiController:AddMissingProductsToShoppingList');
|
$this->get('/stock/add-missing-products-to-shoppinglist', '\Grocy\Controllers\StockApiController:AddMissingProductsToShoppingList');
|
||||||
$this->get('/stock/clear-shopping-list', '\Grocy\Controllers\StockApiController:ClearShoppingList');
|
$this->get('/stock/clear-shopping-list', '\Grocy\Controllers\StockApiController:ClearShoppingList');
|
||||||
$this->get('/stock/external-barcode-lookup/{barcode}', '\Grocy\Controllers\StockApiController:ExternalBarcodeLookup');
|
$this->get('/stock/external-barcode-lookup/{barcode}', '\Grocy\Controllers\StockApiController:ExternalBarcodeLookup');
|
||||||
|
$this->get('/stock/undo-booking/{bookingId}', '\Grocy\Controllers\StockApiController:UndoBooking');
|
||||||
|
|
||||||
// Recipes
|
// Recipes
|
||||||
$this->get('/recipes/add-not-fulfilled-products-to-shopping-list/{recipeId}', '\Grocy\Controllers\RecipesApiController:AddNotFulfilledProductsToShoppingList');
|
$this->get('/recipes/add-not-fulfilled-products-to-shopping-list/{recipeId}', '\Grocy\Controllers\RecipesApiController:AddNotFulfilledProductsToShoppingList');
|
||||||
@@ -122,11 +126,13 @@ $app->group('/api', function()
|
|||||||
$this->get('/chores/track-chore-execution/{choreId}', '\Grocy\Controllers\ChoresApiController:TrackChoreExecution');
|
$this->get('/chores/track-chore-execution/{choreId}', '\Grocy\Controllers\ChoresApiController:TrackChoreExecution');
|
||||||
$this->get('/chores/get-chore-details/{choreId}', '\Grocy\Controllers\ChoresApiController:ChoreDetails');
|
$this->get('/chores/get-chore-details/{choreId}', '\Grocy\Controllers\ChoresApiController:ChoreDetails');
|
||||||
$this->get('/chores/get-current', '\Grocy\Controllers\ChoresApiController:Current');
|
$this->get('/chores/get-current', '\Grocy\Controllers\ChoresApiController:Current');
|
||||||
|
$this->get('/chores/undo-chore-execution/{executionId}', '\Grocy\Controllers\ChoresApiController:UndoChoreExecution');
|
||||||
|
|
||||||
// Batteries
|
// Batteries
|
||||||
$this->get('/batteries/track-charge-cycle/{batteryId}', '\Grocy\Controllers\BatteriesApiController:TrackChargeCycle');
|
$this->get('/batteries/track-charge-cycle/{batteryId}', '\Grocy\Controllers\BatteriesApiController:TrackChargeCycle');
|
||||||
$this->get('/batteries/get-battery-details/{batteryId}', '\Grocy\Controllers\BatteriesApiController:BatteryDetails');
|
$this->get('/batteries/get-battery-details/{batteryId}', '\Grocy\Controllers\BatteriesApiController:BatteryDetails');
|
||||||
$this->get('/batteries/get-current', '\Grocy\Controllers\BatteriesApiController:Current');
|
$this->get('/batteries/get-current', '\Grocy\Controllers\BatteriesApiController:Current');
|
||||||
|
$this->get('/batteries/undo-charge-cycle/{chargeCycleId}', '\Grocy\Controllers\BatteriesApiController:UndoChargeCycle');
|
||||||
|
|
||||||
// Tasks
|
// Tasks
|
||||||
$this->get('/tasks/get-current', '\Grocy\Controllers\TasksApiController:Current');
|
$this->get('/tasks/get-current', '\Grocy\Controllers\TasksApiController:Current');
|
||||||
|
@@ -18,14 +18,14 @@ class BatteriesService extends BaseService
|
|||||||
}
|
}
|
||||||
|
|
||||||
$battery = $this->Database->batteries($batteryId);
|
$battery = $this->Database->batteries($batteryId);
|
||||||
$batteryChargeCylcesCount = $this->Database->battery_charge_cycles()->where('battery_id', $batteryId)->count();
|
$batteryChargeCyclesCount = $this->Database->battery_charge_cycles()->where('battery_id = :1 AND undone = 0', $batteryId)->count();
|
||||||
$batteryLastChargedTime = $this->Database->battery_charge_cycles()->where('battery_id', $batteryId)->max('tracked_time');
|
$batteryLastChargedTime = $this->Database->battery_charge_cycles()->where('battery_id = :1 AND undone = 0', $batteryId)->max('tracked_time');
|
||||||
$nextChargeTime = $this->Database->batteries_current()->where('battery_id', $batteryId)->min('next_estimated_charge_time');
|
$nextChargeTime = $this->Database->batteries_current()->where('battery_id', $batteryId)->min('next_estimated_charge_time');
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'battery' => $battery,
|
'battery' => $battery,
|
||||||
'last_charged' => $batteryLastChargedTime,
|
'last_charged' => $batteryLastChargedTime,
|
||||||
'charge_cycles_count' => $batteryChargeCylcesCount,
|
'charge_cycles_count' => $batteryChargeCyclesCount,
|
||||||
'next_estimated_charge_time' => $nextChargeTime
|
'next_estimated_charge_time' => $nextChargeTime
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ class BatteriesService extends BaseService
|
|||||||
));
|
));
|
||||||
$logRow->save();
|
$logRow->save();
|
||||||
|
|
||||||
return true;
|
return $this->Database->lastInsertId();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function BatteryExists($batteryId)
|
private function BatteryExists($batteryId)
|
||||||
@@ -51,4 +51,19 @@ class BatteriesService extends BaseService
|
|||||||
$batteryRow = $this->Database->batteries()->where('id = :1', $batteryId)->fetch();
|
$batteryRow = $this->Database->batteries()->where('id = :1', $batteryId)->fetch();
|
||||||
return $batteryRow !== null;
|
return $batteryRow !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function UndoChargeCycle($chargeCycleId)
|
||||||
|
{
|
||||||
|
$logRow = $this->Database->battery_charge_cycles()->where('id = :1 AND undone = 0', $chargeCycleId)->fetch();
|
||||||
|
if ($logRow == null)
|
||||||
|
{
|
||||||
|
throw new \Exception('Charge cycle does not exist or was already undone');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update log entry
|
||||||
|
$logRow->update(array(
|
||||||
|
'undone' => 1,
|
||||||
|
'undone_timestamp' => date('Y-m-d H:i:s')
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -21,11 +21,11 @@ class ChoresService extends BaseService
|
|||||||
}
|
}
|
||||||
|
|
||||||
$chore = $this->Database->chores($choreId);
|
$chore = $this->Database->chores($choreId);
|
||||||
$choreTrackedCount = $this->Database->chores_log()->where('chore_id', $choreId)->count();
|
$choreTrackedCount = $this->Database->chores_log()->where('chore_id = :1 AND undone = 0', $choreId)->count();
|
||||||
$choreLastTrackedTime = $this->Database->chores_log()->where('chore_id', $choreId)->max('tracked_time');
|
$choreLastTrackedTime = $this->Database->chores_log()->where('chore_id = :1 AND undone = 0', $choreId)->max('tracked_time');
|
||||||
$nextExeuctionTime = $this->Database->chores_current()->where('chore_id', $choreId)->min('next_estimated_execution_time');
|
$nextExeuctionTime = $this->Database->chores_current()->where('chore_id', $choreId)->min('next_estimated_execution_time');
|
||||||
|
|
||||||
$lastChoreLogRow = $this->Database->chores_log()->where('chore_id = :1 AND tracked_time = :2', $choreId, $choreLastTrackedTime)->fetch();
|
$lastChoreLogRow = $this->Database->chores_log()->where('chore_id = :1 AND tracked_time = :2 AND undone = 0', $choreId, $choreLastTrackedTime)->fetch();
|
||||||
$lastDoneByUser = null;
|
$lastDoneByUser = null;
|
||||||
if ($lastChoreLogRow !== null && !empty($lastChoreLogRow))
|
if ($lastChoreLogRow !== null && !empty($lastChoreLogRow))
|
||||||
{
|
{
|
||||||
@@ -63,7 +63,7 @@ class ChoresService extends BaseService
|
|||||||
));
|
));
|
||||||
$logRow->save();
|
$logRow->save();
|
||||||
|
|
||||||
return true;
|
return $this->Database->lastInsertId();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function ChoreExists($choreId)
|
private function ChoreExists($choreId)
|
||||||
@@ -71,4 +71,19 @@ class ChoresService extends BaseService
|
|||||||
$choreRow = $this->Database->chores()->where('id = :1', $choreId)->fetch();
|
$choreRow = $this->Database->chores()->where('id = :1', $choreId)->fetch();
|
||||||
return $choreRow !== null;
|
return $choreRow !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function UndoChoreExecution($executionId)
|
||||||
|
{
|
||||||
|
$logRow = $this->Database->chores_log()->where('id = :1 AND undone = 0', $executionId)->fetch();
|
||||||
|
if ($logRow == null)
|
||||||
|
{
|
||||||
|
throw new \Exception('Execution does not exist or was already undone');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update log entry
|
||||||
|
$logRow->update(array(
|
||||||
|
'undone' => 1,
|
||||||
|
'undone_timestamp' => date('Y-m-d H:i:s')
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -31,6 +31,9 @@ class DemoDataGeneratorService extends BaseService
|
|||||||
INSERT INTO quantity_units (name, name_plural) VALUES ('{$localizationService->Localize('Can')}', '{$localizationService->Localize('Cans')}'); --6
|
INSERT INTO quantity_units (name, name_plural) VALUES ('{$localizationService->Localize('Can')}', '{$localizationService->Localize('Cans')}'); --6
|
||||||
INSERT INTO quantity_units (name, name_plural) VALUES ('{$localizationService->Localize('Bunch')}', '{$localizationService->Localize('Bunches')}'); --7
|
INSERT INTO quantity_units (name, name_plural) VALUES ('{$localizationService->Localize('Bunch')}', '{$localizationService->Localize('Bunches')}'); --7
|
||||||
INSERT INTO quantity_units (name, name_plural) VALUES ('{$localizationService->Localize('Gram')}', '{$localizationService->Localize('Grams')}'); --8
|
INSERT INTO quantity_units (name, name_plural) VALUES ('{$localizationService->Localize('Gram')}', '{$localizationService->Localize('Grams')}'); --8
|
||||||
|
INSERT INTO quantity_units (name, name_plural) VALUES ('{$localizationService->Localize('Liter')}', '{$localizationService->Localize('Liters')}'); --9
|
||||||
|
INSERT INTO quantity_units (name, name_plural) VALUES ('{$localizationService->Localize('Bottle')}', '{$localizationService->Localize('Bottles')}'); --10
|
||||||
|
INSERT INTO quantity_units (name, name_plural) VALUES ('{$localizationService->Localize('Milliliter')}', '{$localizationService->Localize('Milliliters')}'); --11
|
||||||
|
|
||||||
INSERT INTO product_groups(name) VALUES ('01 {$localizationService->Localize('Sweets')}'); --1
|
INSERT INTO product_groups(name) VALUES ('01 {$localizationService->Localize('Sweets')}'); --1
|
||||||
INSERT INTO product_groups(name) VALUES ('02 {$localizationService->Localize('Bakery products')}'); --2
|
INSERT INTO product_groups(name) VALUES ('02 {$localizationService->Localize('Bakery products')}'); --2
|
||||||
@@ -62,6 +65,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 ('{$localizationService->Localize('Minced meat')}', 2, 3, 3, 1, 4); --20
|
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id) VALUES ('{$localizationService->Localize('Minced meat')}', 2, 3, 3, 1, 4); --20
|
||||||
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id) VALUES ('{$localizationService->Localize('Flour')}', 2, 3, 3, 1, 3); --21
|
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id) VALUES ('{$localizationService->Localize('Flour')}', 2, 3, 3, 1, 3); --21
|
||||||
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id) VALUES ('{$localizationService->Localize('Sugar')}', 3, 3, 3, 1, 3); --22
|
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock, product_group_id) VALUES ('{$localizationService->Localize('Sugar')}', 3, 3, 3, 1, 3); --22
|
||||||
|
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('{$localizationService->Localize('Milk')}', 2, 10, 10, 1); --23
|
||||||
|
|
||||||
INSERT INTO shopping_list (note, amount) VALUES ('{$localizationService->Localize('Some good snacks')}', 1);
|
INSERT INTO shopping_list (note, amount) VALUES ('{$localizationService->Localize('Some good snacks')}', 1);
|
||||||
INSERT INTO shopping_list (product_id, amount) VALUES (20, 1);
|
INSERT INTO shopping_list (product_id, amount) VALUES (20, 1);
|
||||||
@@ -71,11 +75,13 @@ class DemoDataGeneratorService extends BaseService
|
|||||||
INSERT INTO recipes (name, description) VALUES ('{$localizationService->Localize('Spaghetti bolognese')}', '{$loremIpsumWithHtmlFormattings}'); --2
|
INSERT INTO recipes (name, description) VALUES ('{$localizationService->Localize('Spaghetti bolognese')}', '{$loremIpsumWithHtmlFormattings}'); --2
|
||||||
INSERT INTO recipes (name, description) VALUES ('{$localizationService->Localize('Sandwiches')}', '{$loremIpsumWithHtmlFormattings}'); --3
|
INSERT INTO recipes (name, description) VALUES ('{$localizationService->Localize('Sandwiches')}', '{$loremIpsumWithHtmlFormattings}'); --3
|
||||||
INSERT INTO recipes (name, description) VALUES ('{$localizationService->Localize('Pancakes')}', '{$loremIpsumWithHtmlFormattings}'); --4
|
INSERT INTO recipes (name, description) VALUES ('{$localizationService->Localize('Pancakes')}', '{$loremIpsumWithHtmlFormattings}'); --4
|
||||||
|
INSERT INTO recipes (name, description) VALUES ('{$localizationService->Localize('Chocolate sauce')}', '{$loremIpsumWithHtmlFormattings}'); --5
|
||||||
|
INSERT INTO recipes (name, description) VALUES ('{$localizationService->Localize('Pancakes')} / {$localizationService->Localize('Chocolate sauce')}', '{$loremIpsumWithHtmlFormattings}'); --6
|
||||||
|
|
||||||
INSERT INTO recipes_pos (recipe_id, product_id, amount) VALUES (1, 16, 1);
|
INSERT INTO recipes_pos (recipe_id, product_id, amount, ingredient_group) VALUES (1, 16, 1, '{$localizationService->Localize('Bottom')}');
|
||||||
INSERT INTO recipes_pos (recipe_id, product_id, amount) VALUES (1, 17, 1);
|
INSERT INTO recipes_pos (recipe_id, product_id, amount, ingredient_group) VALUES (1, 17, 1, '{$localizationService->Localize('Topping')}');
|
||||||
INSERT INTO recipes_pos (recipe_id, product_id, amount, note) VALUES (1, 18, 1, '{$localizationService->Localize('This is the note content of the recipe ingredient')}');
|
INSERT INTO recipes_pos (recipe_id, product_id, amount, note, ingredient_group) VALUES (1, 18, 1, '{$localizationService->Localize('This is the note content of the recipe ingredient')}', '{$localizationService->Localize('Topping')}');
|
||||||
INSERT INTO recipes_pos (recipe_id, product_id, amount) VALUES (1, 10, 1);
|
INSERT INTO recipes_pos (recipe_id, product_id, amount, ingredient_group) VALUES (1, 10, 1, '{$localizationService->Localize('Bottom')}');
|
||||||
INSERT INTO recipes_pos (recipe_id, product_id, amount) VALUES (2, 6, 1);
|
INSERT INTO recipes_pos (recipe_id, product_id, amount) VALUES (2, 6, 1);
|
||||||
INSERT INTO recipes_pos (recipe_id, product_id, amount) VALUES (2, 10, 1);
|
INSERT INTO recipes_pos (recipe_id, product_id, amount) VALUES (2, 10, 1);
|
||||||
INSERT INTO recipes_pos (recipe_id, product_id, amount, note) VALUES (2, 17, 1, '{$localizationService->Localize('This is the note content of the recipe ingredient')}');
|
INSERT INTO recipes_pos (recipe_id, product_id, amount, note) VALUES (2, 17, 1, '{$localizationService->Localize('This is the note content of the recipe ingredient')}');
|
||||||
@@ -85,6 +91,11 @@ class DemoDataGeneratorService extends BaseService
|
|||||||
INSERT INTO recipes_pos (recipe_id, product_id, amount) VALUES (4, 5, 4);
|
INSERT INTO recipes_pos (recipe_id, product_id, amount) VALUES (4, 5, 4);
|
||||||
INSERT INTO recipes_pos (recipe_id, product_id, amount, qu_id, only_check_single_unit_in_stock) VALUES (4, 21, 200, 8, 1);
|
INSERT INTO recipes_pos (recipe_id, product_id, amount, qu_id, only_check_single_unit_in_stock) VALUES (4, 21, 200, 8, 1);
|
||||||
INSERT INTO recipes_pos (recipe_id, product_id, amount, qu_id, only_check_single_unit_in_stock) VALUES (4, 22, 200, 8, 1);
|
INSERT INTO recipes_pos (recipe_id, product_id, amount, qu_id, only_check_single_unit_in_stock) VALUES (4, 22, 200, 8, 1);
|
||||||
|
INSERT INTO recipes_pos (recipe_id, product_id, amount) VALUES (5, 2, 1);
|
||||||
|
INSERT INTO recipes_pos (recipe_id, product_id, amount, qu_id, only_check_single_unit_in_stock) VALUES (5, 23, 200, 11, 1);
|
||||||
|
|
||||||
|
INSERt INTO recipes_nestings(recipe_id, includes_recipe_id) VALUES (6, 4);
|
||||||
|
INSERt INTO recipes_nestings(recipe_id, includes_recipe_id) VALUES (6, 5);
|
||||||
|
|
||||||
INSERT INTO chores (name, period_type, period_days) VALUES ('{$localizationService->Localize('Changed towels in the bathroom')}', 'manually', 5); --1
|
INSERT INTO chores (name, period_type, period_days) VALUES ('{$localizationService->Localize('Changed towels in the bathroom')}', 'manually', 5); --1
|
||||||
INSERT INTO chores (name, period_type, period_days) VALUES ('{$localizationService->Localize('Cleaned the kitchen floor')}', 'dynamic-regular', 7); --2
|
INSERT INTO chores (name, period_type, period_days) VALUES ('{$localizationService->Localize('Cleaned the kitchen floor')}', 'dynamic-regular', 7); --2
|
||||||
@@ -184,6 +195,8 @@ class DemoDataGeneratorService extends BaseService
|
|||||||
$stockService->AddProduct(21, 1, date('Y-m-d', strtotime('+200 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice());
|
$stockService->AddProduct(21, 1, date('Y-m-d', strtotime('+200 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice());
|
||||||
$stockService->AddProduct(22, 1, date('Y-m-d', strtotime('+200 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice());
|
$stockService->AddProduct(22, 1, date('Y-m-d', strtotime('+200 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-10 days')), $this->RandomPrice());
|
||||||
$stockService->AddProduct(22, 1, date('Y-m-d', strtotime('+200 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice());
|
$stockService->AddProduct(22, 1, date('Y-m-d', strtotime('+200 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-20 days')), $this->RandomPrice());
|
||||||
|
$stockService->AddProduct(23, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-40 days')), $this->RandomPrice());
|
||||||
|
$stockService->AddProduct(23, 1, date('Y-m-d', strtotime('+2 days')), StockService::TRANSACTION_TYPE_PURCHASE, date('Y-m-d', strtotime('-50 days')), $this->RandomPrice());
|
||||||
$stockService->AddMissingProductsToShoppingList();
|
$stockService->AddMissingProductsToShoppingList();
|
||||||
|
|
||||||
$choresService = new ChoresService();
|
$choresService = new ChoresService();
|
||||||
|
@@ -37,10 +37,10 @@ class SessionService extends BaseService
|
|||||||
{
|
{
|
||||||
$newSessionKey = $this->GenerateSessionKey();
|
$newSessionKey = $this->GenerateSessionKey();
|
||||||
|
|
||||||
$expires = date('Y-m-d H:i:s', time() + 2592000); // Default is that sessions expire in 30 days
|
$expires = date('Y-m-d H:i:s', intval(time() + 2592000)); // Default is that sessions expire in 30 days
|
||||||
if ($stayLoggedInPermanently === true)
|
if ($stayLoggedInPermanently === true)
|
||||||
{
|
{
|
||||||
$expires = date('Y-m-d H:i:s', time() + 31220640000); // 999 years aka forever
|
$expires = date('Y-m-d H:i:s', intval(time() + 31220640000)); // 999 years aka forever
|
||||||
}
|
}
|
||||||
|
|
||||||
$sessionRow = $this->Database->sessions()->createRow(array(
|
$sessionRow = $this->Database->sessions()->createRow(array(
|
||||||
|
@@ -47,14 +47,14 @@ class StockService extends BaseService
|
|||||||
|
|
||||||
$product = $this->Database->products($productId);
|
$product = $this->Database->products($productId);
|
||||||
$productStockAmount = $this->Database->stock()->where('product_id', $productId)->sum('amount');
|
$productStockAmount = $this->Database->stock()->where('product_id', $productId)->sum('amount');
|
||||||
$productLastPurchased = $this->Database->stock_log()->where('product_id', $productId)->where('transaction_type', self::TRANSACTION_TYPE_PURCHASE)->max('purchased_date');
|
$productLastPurchased = $this->Database->stock_log()->where('product_id', $productId)->where('transaction_type', self::TRANSACTION_TYPE_PURCHASE)->where('undone', 0)->max('purchased_date');
|
||||||
$productLastUsed = $this->Database->stock_log()->where('product_id', $productId)->where('transaction_type', self::TRANSACTION_TYPE_CONSUME)->max('used_date');
|
$productLastUsed = $this->Database->stock_log()->where('product_id', $productId)->where('transaction_type', self::TRANSACTION_TYPE_CONSUME)->where('undone', 0)->max('used_date');
|
||||||
$nextBestBeforeDate = $this->Database->stock()->where('product_id', $productId)->min('best_before_date');
|
$nextBestBeforeDate = $this->Database->stock()->where('product_id', $productId)->min('best_before_date');
|
||||||
$quPurchase = $this->Database->quantity_units($product->qu_id_purchase);
|
$quPurchase = $this->Database->quantity_units($product->qu_id_purchase);
|
||||||
$quStock = $this->Database->quantity_units($product->qu_id_stock);
|
$quStock = $this->Database->quantity_units($product->qu_id_stock);
|
||||||
|
|
||||||
$lastPrice = null;
|
$lastPrice = null;
|
||||||
$lastLogRow = $this->Database->stock_log()->where('product_id = :1 AND transaction_type = :2', $productId, self::TRANSACTION_TYPE_PURCHASE)->orderBy('row_created_timestamp', 'DESC')->limit(1)->fetch();
|
$lastLogRow = $this->Database->stock_log()->where('product_id = :1 AND transaction_type = :2 AND undone = 0', $productId, self::TRANSACTION_TYPE_PURCHASE)->orderBy('row_created_timestamp', 'DESC')->limit(1)->fetch();
|
||||||
if ($lastLogRow !== null && !empty($lastLogRow))
|
if ($lastLogRow !== null && !empty($lastLogRow))
|
||||||
{
|
{
|
||||||
$lastPrice = $lastLogRow->price;
|
$lastPrice = $lastLogRow->price;
|
||||||
@@ -80,7 +80,7 @@ class StockService extends BaseService
|
|||||||
}
|
}
|
||||||
|
|
||||||
$returnData = array();
|
$returnData = array();
|
||||||
$rows = $this->Database->stock_log()->where('product_id = :1 AND transaction_type = :2', $productId, self::TRANSACTION_TYPE_PURCHASE)->whereNOT('price', null)->orderBy('purchased_date', 'DESC');
|
$rows = $this->Database->stock_log()->where('product_id = :1 AND transaction_type = :2 AND undone = 0', $productId, self::TRANSACTION_TYPE_PURCHASE)->whereNOT('price', null)->orderBy('purchased_date', 'DESC');
|
||||||
foreach ($rows as $row)
|
foreach ($rows as $row)
|
||||||
{
|
{
|
||||||
$returnData[] = array(
|
$returnData[] = array(
|
||||||
@@ -113,6 +113,8 @@ class StockService extends BaseService
|
|||||||
));
|
));
|
||||||
$logRow->save();
|
$logRow->save();
|
||||||
|
|
||||||
|
$returnValue = $this->Database->lastInsertId();
|
||||||
|
|
||||||
$stockRow = $this->Database->stock()->createRow(array(
|
$stockRow = $this->Database->stock()->createRow(array(
|
||||||
'product_id' => $productId,
|
'product_id' => $productId,
|
||||||
'amount' => $amount,
|
'amount' => $amount,
|
||||||
@@ -123,7 +125,7 @@ class StockService extends BaseService
|
|||||||
));
|
));
|
||||||
$stockRow->save();
|
$stockRow->save();
|
||||||
|
|
||||||
return true;
|
return $returnValue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -197,7 +199,7 @@ class StockService extends BaseService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return $this->Database->lastInsertId();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -226,7 +228,7 @@ class StockService extends BaseService
|
|||||||
$this->ConsumeProduct($productId, $amountToRemove, false, self::TRANSACTION_TYPE_INVENTORY_CORRECTION);
|
$this->ConsumeProduct($productId, $amountToRemove, false, self::TRANSACTION_TYPE_INVENTORY_CORRECTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return $this->Database->lastInsertId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function AddMissingProductsToShoppingList()
|
public function AddMissingProductsToShoppingList()
|
||||||
@@ -305,4 +307,55 @@ class StockService extends BaseService
|
|||||||
|
|
||||||
return $pluginOutput;
|
return $pluginOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function UndoBooking($bookingId)
|
||||||
|
{
|
||||||
|
$logRow = $this->Database->stock_log()->where('id = :1 AND undone = 0', $bookingId)->fetch();
|
||||||
|
if ($logRow == null)
|
||||||
|
{
|
||||||
|
throw new \Exception('Booking does not exist or was already undone');
|
||||||
|
}
|
||||||
|
|
||||||
|
$hasSubsequentBookings = $this->Database->stock_log()->where('stock_id = :1 AND id != :2 AND id > :2', $logRow->stock_id, $logRow->id)->count() > 0;
|
||||||
|
if ($hasSubsequentBookings)
|
||||||
|
{
|
||||||
|
throw new \Exception('Booking has subsequent dependent bookings, undo not possible');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($logRow->transaction_type === self::TRANSACTION_TYPE_PURCHASE || ($logRow->transaction_type === self::TRANSACTION_TYPE_INVENTORY_CORRECTION && $logRow->amount > 0))
|
||||||
|
{
|
||||||
|
// Remove corresponding stock entry
|
||||||
|
$stockRows = $this->Database->stock()->where('stock_id', $logRow->stock_id);
|
||||||
|
$stockRows->delete();
|
||||||
|
|
||||||
|
// Update log entry
|
||||||
|
$logRow->update(array(
|
||||||
|
'undone' => 1,
|
||||||
|
'undone_timestamp' => date('Y-m-d H:i:s')
|
||||||
|
));
|
||||||
|
}
|
||||||
|
elseif ($logRow->transaction_type === self::TRANSACTION_TYPE_CONSUME || ($logRow->transaction_type === self::TRANSACTION_TYPE_INVENTORY_CORRECTION && $logRow->amount < 0))
|
||||||
|
{
|
||||||
|
// Add corresponding amount back to stock
|
||||||
|
$stockRow = $this->Database->stock()->createRow(array(
|
||||||
|
'product_id' => $logRow->product_id,
|
||||||
|
'amount' => $logRow->amount * -1,
|
||||||
|
'best_before_date' => $logRow->best_before_date,
|
||||||
|
'purchased_date' => $logRow->purchased_date,
|
||||||
|
'stock_id' => $logRow->stock_id,
|
||||||
|
'price' => $logRow->price
|
||||||
|
));
|
||||||
|
$stockRow->save();
|
||||||
|
|
||||||
|
// Update log entry
|
||||||
|
$logRow->update(array(
|
||||||
|
'undone' => 1,
|
||||||
|
'undone_timestamp' => date('Y-m-d H:i:s')
|
||||||
|
));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new \Exception('This booking cannot be undone');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"Version": "1.21.0",
|
"Version": "1.22.0",
|
||||||
"ReleaseDate": "2018-10-06"
|
"ReleaseDate": "2018-10-27"
|
||||||
}
|
}
|
||||||
|
66
views/batteriesjournal.blade.php
Normal file
66
views/batteriesjournal.blade.php
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
@extends('layout.default')
|
||||||
|
|
||||||
|
@section('title', $L('Batteries journal'))
|
||||||
|
@section('activeNav', 'batteriesjournal')
|
||||||
|
@section('viewJsName', 'batteriesjournal')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h1>@yield('title')</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row my-3">
|
||||||
|
<div class="col-xs-12 col-md-6 col-xl-3">
|
||||||
|
<label for="battery-filter">{{ $L('Filter by battery') }}</label> <i class="fas fa-filter"></i>
|
||||||
|
<select class="form-control" id="battery-filter">
|
||||||
|
<option value="all">{{ $L('All') }}</option>
|
||||||
|
@foreach($batteries as $battery)
|
||||||
|
<option value="{{ $battery->id }}">{{ $battery->name }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-12 col-md-6 col-xl-3">
|
||||||
|
<label for="search">{{ $L('Search') }}</label> <i class="fas fa-search"></i>
|
||||||
|
<input type="text" class="form-control" id="search">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<table id="batteries-journal-table" class="table table-sm table-striped dt-responsive">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>{{ $L('Battery') }}</th>
|
||||||
|
<th>{{ $L('Tracked time') }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach($chargeCycles as $chargeCycleEntry)
|
||||||
|
<tr class="@if($chargeCycleEntry->undone == 1) text-muted @endif">
|
||||||
|
<td class="fit-content">
|
||||||
|
<a class="btn btn-secondary btn-sm undo-battery-execution-button @if($chargeCycleEntry->undone == 1) disabled @endif" href="#" data-charge-cycle-id="{{ $chargeCycleEntry->id }}" data-toggle="tooltip" data-placement="left" title="{{ $L('Undo charge cycle') }}">
|
||||||
|
<i class="fas fa-undo"></i>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="@if($chargeCycleEntry->undone == 1) text-strike-through @endif">{{ FindObjectInArrayByPropertyValue($batteries, 'id', $chargeCycleEntry->battery_id)->name }}</span>
|
||||||
|
@if($chargeCycleEntry->undone == 1)
|
||||||
|
<br>
|
||||||
|
{{ $L('Undone on') . ' ' . $chargeCycleEntry->undone_timestamp }}
|
||||||
|
<time class="timeago timeago-contextual" datetime="{{ $chargeCycleEntry->undone_timestamp }}"></time>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ $chargeCycleEntry->tracked_time }}
|
||||||
|
<time class="timeago timeago-contextual" datetime="{{ $chargeCycleEntry->tracked_time }}"></time>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@stop
|
@@ -11,7 +11,11 @@
|
|||||||
@section('content')
|
@section('content')
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h1>@yield('title')</h1>
|
<h1>@yield('title')
|
||||||
|
<a class="btn btn-outline-dark responsive-button" href="{{ $U('/batteriesjournal') }}">
|
||||||
|
<i class="fas fa-file-alt"></i> {{ $L('Journal') }}
|
||||||
|
</a>
|
||||||
|
</h1>
|
||||||
<p id="info-due-batteries" data-status-filter="duesoon" data-next-x-days="{{ $nextXDays }}" class="btn btn-lg btn-warning status-filter-button responsive-button mr-2"></p>
|
<p id="info-due-batteries" data-status-filter="duesoon" data-next-x-days="{{ $nextXDays }}" class="btn btn-lg btn-warning status-filter-button responsive-button mr-2"></p>
|
||||||
<p id="info-overdue-batteries" data-status-filter="overdue" class="btn btn-lg btn-danger status-filter-button responsive-button"></p>
|
<p id="info-overdue-batteries" data-status-filter="overdue" class="btn btn-lg btn-danger status-filter-button responsive-button"></p>
|
||||||
</div>
|
</div>
|
||||||
@@ -53,6 +57,9 @@
|
|||||||
data-battery-name="{{ FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->name }}">
|
data-battery-name="{{ FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->name }}">
|
||||||
<i class="fas fa-fire"></i>
|
<i class="fas fa-fire"></i>
|
||||||
</a>
|
</a>
|
||||||
|
<a class="btn btn-info btn-sm" href="{{ $U('/batteriesjournal?battery=') }}{{ $curentBatteryEntry->battery_id }}">
|
||||||
|
<i class="fas fa-file-alt"></i>
|
||||||
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->name }}
|
{{ FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->name }}
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
@extends('layout.default')
|
@extends('layout.default')
|
||||||
|
|
||||||
@section('title', $L('Chores analysis'))
|
@section('title', $L('Chores journal'))
|
||||||
@section('activeNav', 'choresanalysis')
|
@section('activeNav', 'choresjournal')
|
||||||
@section('viewJsName', 'choresanalysis')
|
@section('viewJsName', 'choresjournal')
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row mt-3">
|
<div class="row my-3">
|
||||||
<div class="col-xs-12 col-md-6 col-xl-3">
|
<div class="col-xs-12 col-md-6 col-xl-3">
|
||||||
<label for="chore-filter">{{ $L('Filter by chore') }}</label> <i class="fas fa-filter"></i>
|
<label for="chore-filter">{{ $L('Filter by chore') }}</label> <i class="fas fa-filter"></i>
|
||||||
<select class="form-control" id="chore-filter">
|
<select class="form-control" id="chore-filter">
|
||||||
@@ -29,9 +29,10 @@
|
|||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<table id="chores-analysis-table" class="table table-sm table-striped dt-responsive">
|
<table id="chores-journal-table" class="table table-sm table-striped dt-responsive">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
<th>{{ $L('Chore') }}</th>
|
<th>{{ $L('Chore') }}</th>
|
||||||
<th>{{ $L('Tracked time') }}</th>
|
<th>{{ $L('Tracked time') }}</th>
|
||||||
<th>{{ $L('Done by') }}</th>
|
<th>{{ $L('Done by') }}</th>
|
||||||
@@ -39,13 +40,23 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@foreach($choresLog as $choreLogEntry)
|
@foreach($choresLog as $choreLogEntry)
|
||||||
<tr>
|
<tr class="@if($choreLogEntry->undone == 1) text-muted @endif">
|
||||||
|
<td class="fit-content">
|
||||||
|
<a class="btn btn-secondary btn-sm undo-chore-execution-button @if($choreLogEntry->undone == 1) disabled @endif" href="#" data-execution-id="{{ $choreLogEntry->id }}" data-toggle="tooltip" data-placement="left" title="{{ $L('Undo chore execution') }}">
|
||||||
|
<i class="fas fa-undo"></i>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ FindObjectInArrayByPropertyValue($chores, 'id', $choreLogEntry->chore_id)->name }}
|
<span class="@if($choreLogEntry->undone == 1) text-strike-through @endif">{{ FindObjectInArrayByPropertyValue($chores, 'id', $choreLogEntry->chore_id)->name }}</span>
|
||||||
|
@if($choreLogEntry->undone == 1)
|
||||||
|
<br>
|
||||||
|
{{ $L('Undone on') . ' ' . $choreLogEntry->undone_timestamp }}
|
||||||
|
<time class="timeago timeago-contextual" datetime="{{ $choreLogEntry->undone_timestamp }}"></time>
|
||||||
|
@endif
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ $choreLogEntry->tracked_time }}
|
{{ $choreLogEntry->tracked_time }}
|
||||||
<time class="timeago timeago-contextual" datetime="{{ $choreLogEntry->tracked_time }}"></time>
|
<time class="timeago timeago-contextual" datetime="{{ $choreLogEntry->tracked_time }}"></time>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@if ($choreLogEntry->done_by_user_id !== null && !empty($choreLogEntry->done_by_user_id))
|
@if ($choreLogEntry->done_by_user_id !== null && !empty($choreLogEntry->done_by_user_id))
|
@@ -11,7 +11,11 @@
|
|||||||
@section('content')
|
@section('content')
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h1>@yield('title')</h1>
|
<h1>@yield('title')
|
||||||
|
<a class="btn btn-outline-dark responsive-button" href="{{ $U('/choresjournal') }}">
|
||||||
|
<i class="fas fa-file-alt"></i> {{ $L('Journal') }}
|
||||||
|
</a>
|
||||||
|
</h1>
|
||||||
<p id="info-due-chores" data-status-filter="duesoon" data-next-x-days="{{ $nextXDays }}" class="btn btn-lg btn-warning status-filter-button responsive-button mr-2"></p>
|
<p id="info-due-chores" data-status-filter="duesoon" data-next-x-days="{{ $nextXDays }}" class="btn btn-lg btn-warning status-filter-button responsive-button mr-2"></p>
|
||||||
<p id="info-overdue-chores" data-status-filter="overdue" class="btn btn-lg btn-danger status-filter-button responsive-button"></p>
|
<p id="info-overdue-chores" data-status-filter="overdue" class="btn btn-lg btn-danger status-filter-button responsive-button"></p>
|
||||||
</div>
|
</div>
|
||||||
@@ -53,8 +57,8 @@
|
|||||||
data-chore-name="{{ FindObjectInArrayByPropertyValue($chores, 'id', $curentChoreEntry->chore_id)->name }}">
|
data-chore-name="{{ FindObjectInArrayByPropertyValue($chores, 'id', $curentChoreEntry->chore_id)->name }}">
|
||||||
<i class="fas fa-play"></i>
|
<i class="fas fa-play"></i>
|
||||||
</a>
|
</a>
|
||||||
<a class="btn btn-info btn-sm" href="{{ $U('/choresanalysis?chore=') }}{{ $curentChoreEntry->chore_id }}">
|
<a class="btn btn-info btn-sm" href="{{ $U('/choresjournal?chore=') }}{{ $curentChoreEntry->chore_id }}">
|
||||||
<i class="fas fa-chart-line"></i>
|
<i class="fas fa-file-alt"></i>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
@@ -5,6 +5,9 @@
|
|||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<i class="fas fa-battery-three-quarters"></i> {{ $L('Battery overview') }}
|
<i class="fas fa-battery-three-quarters"></i> {{ $L('Battery overview') }}
|
||||||
|
<a id="batterycard-battery-edit-button" class="btn btn-sm btn-outline-info py-0 float-right disabled" href="#" data-toggle="tooltip" title="{{ $L('Edit battery') }}">
|
||||||
|
<i class="fas fa-edit"></i>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h3><span id="batterycard-battery-name"></span></h3>
|
<h3><span id="batterycard-battery-name"></span></h3>
|
||||||
|
@@ -4,7 +4,10 @@
|
|||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<i class="fas fa-refresh"></i> {{ $L('Chore overview') }}
|
<i class="fas fa-home"></i> {{ $L('Chore overview') }}
|
||||||
|
<a id="chorecard-chore-edit-button" class="btn btn-sm btn-outline-info py-0 float-right disabled" href="#" data-toggle="tooltip" title="{{ $L('Edit chore') }}">
|
||||||
|
<i class="fas fa-edit"></i>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h3><span id="chorecard-chore-name"></span></h3>
|
<h3><span id="chorecard-chore-name"></span></h3>
|
||||||
|
@@ -6,6 +6,9 @@
|
|||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<i class="fab fa-product-hunt"></i> {{ $L('Product overview') }}
|
<i class="fab fa-product-hunt"></i> {{ $L('Product overview') }}
|
||||||
|
<a id="productcard-product-edit-button" class="btn btn-sm btn-outline-info py-0 float-right disabled" href="#" data-toggle="tooltip" title="{{ $L('Edit product') }}">
|
||||||
|
<i class="fas fa-edit"></i>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h3><span id="productcard-product-name"></span></h3>
|
<h3><span id="productcard-product-name"></span></h3>
|
||||||
@@ -17,7 +20,7 @@
|
|||||||
|
|
||||||
<h5 class="mt-3">{{ $L('Product picture') }}</h5>
|
<h5 class="mt-3">{{ $L('Product picture') }}</h5>
|
||||||
<img id="productcard-product-picture" src="" class="img-fluid img-thumbnail d-none">
|
<img id="productcard-product-picture" src="" class="img-fluid img-thumbnail d-none">
|
||||||
<span id="productcard-no-product-picture" class="font-italic d-none">{{ $L('No picture') }}</span>
|
<span id="productcard-no-product-picture" class="font-italic d-none">{{ $L('No picture available') }}</span>
|
||||||
|
|
||||||
<h5 class="mt-3">{{ $L('Price history') }}</h5>
|
<h5 class="mt-3">{{ $L('Price history') }}</h5>
|
||||||
<canvas id="productcard-product-price-history-chart" class="w-100 d-none"></canvas>
|
<canvas id="productcard-product-price-history-chart" class="w-100 d-none"></canvas>
|
||||||
|
@@ -46,6 +46,7 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="location_id">{{ $L('Location') }}</label>
|
<label for="location_id">{{ $L('Location') }}</label>
|
||||||
<select required class="form-control" id="location_id" name="location_id">
|
<select required class="form-control" id="location_id" name="location_id">
|
||||||
|
<option></option>
|
||||||
@foreach($locations as $location)
|
@foreach($locations as $location)
|
||||||
<option @if($mode == 'edit' && $location->id == $product->location_id) selected="selected" @endif value="{{ $location->id }}">{{ $location->name }}</option>
|
<option @if($mode == 'edit' && $location->id == $product->location_id) selected="selected" @endif value="{{ $location->id }}">{{ $location->name }}</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
@@ -85,6 +86,7 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="qu_id_purchase">{{ $L('Quantity unit purchase') }}</label>
|
<label for="qu_id_purchase">{{ $L('Quantity unit purchase') }}</label>
|
||||||
<select required class="form-control input-group-qu" id="qu_id_purchase" name="qu_id_purchase">
|
<select required class="form-control input-group-qu" id="qu_id_purchase" name="qu_id_purchase">
|
||||||
|
<option></option>
|
||||||
@foreach($quantityunits as $quantityunit)
|
@foreach($quantityunits as $quantityunit)
|
||||||
<option @if($mode == 'edit' && $quantityunit->id == $product->qu_id_purchase) selected="selected" @endif value="{{ $quantityunit->id }}">{{ $quantityunit->name }}</option>
|
<option @if($mode == 'edit' && $quantityunit->id == $product->qu_id_purchase) selected="selected" @endif value="{{ $quantityunit->id }}">{{ $quantityunit->name }}</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
@@ -95,6 +97,7 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="qu_id_stock">{{ $L('Quantity unit stock') }}</label>
|
<label for="qu_id_stock">{{ $L('Quantity unit stock') }}</label>
|
||||||
<select required class="form-control input-group-qu" id="qu_id_stock" name="qu_id_stock">
|
<select required class="form-control input-group-qu" id="qu_id_stock" name="qu_id_stock">
|
||||||
|
<option></option>
|
||||||
@foreach($quantityunits as $quantityunit)
|
@foreach($quantityunits as $quantityunit)
|
||||||
<option @if($mode == 'edit' && $quantityunit->id == $product->qu_id_stock) selected="selected" @endif value="{{ $quantityunit->id }}">{{ $quantityunit->name }}</option>
|
<option @if($mode == 'edit' && $quantityunit->id == $product->qu_id_stock) selected="selected" @endif value="{{ $quantityunit->id }}">{{ $quantityunit->name }}</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
@@ -133,7 +136,7 @@
|
|||||||
<p><img id="current-product-picture" src="{{ $U('/api/file/productpictures?file_name=' . $product->picture_file_name) }}" class="img-fluid img-thumbnail mt-2"></p>
|
<p><img id="current-product-picture" src="{{ $U('/api/file/productpictures?file_name=' . $product->picture_file_name) }}" class="img-fluid img-thumbnail mt-2"></p>
|
||||||
<p id="delete-current-product-picture-on-save-hint" class="form-text text-muted font-italic d-none">{{ $L('The current picture will be deleted when you save the product') }}</p>
|
<p id="delete-current-product-picture-on-save-hint" class="form-text text-muted font-italic d-none">{{ $L('The current picture will be deleted when you save the product') }}</p>
|
||||||
@else
|
@else
|
||||||
<p id="no-current-product-picture-hint" class="form-text text-muted font-italic">{{ $L('No picture') }}</p>
|
<p id="no-current-product-picture-hint" class="form-text text-muted font-italic">{{ $L('No picture available') }}</p>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
45
views/productpresets.blade.php
Normal file
45
views/productpresets.blade.php
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
@extends('layout.default')
|
||||||
|
|
||||||
|
@section('title', $L('Presets for new products'))
|
||||||
|
|
||||||
|
@section('viewJsName', 'productpresets')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6 col-xs-12">
|
||||||
|
<h1>@yield('title')</h1>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="product_presets_location_id">{{ $L('Location') }}</label>
|
||||||
|
<select class="form-control user-setting-control" id="product_presets_location_id" data-setting-key="product_presets_location_id">
|
||||||
|
<option value="-1"></option>
|
||||||
|
@foreach($locations as $location)
|
||||||
|
<option value="{{ $location->id }}">{{ $location->name }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="product_presets_product_group_id">{{ $L('Product group') }}</label>
|
||||||
|
<select class="form-control user-setting-control" id="product_presets_product_group_id" data-setting-key="product_presets_product_group_id">
|
||||||
|
<option value="-1"></option>
|
||||||
|
@foreach($productGroups as $productGroup)
|
||||||
|
<option value="{{ $productGroup->id }}">{{ $productGroup->name }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="product_presets_qu_id">{{ $L('Quantity unit') }}</label>
|
||||||
|
<select class="form-control user-setting-control" id="product_presets_qu_id" data-setting-key="product_presets_qu_id">
|
||||||
|
<option value="-1"></option>
|
||||||
|
@foreach($quantityunits as $quantityunit)
|
||||||
|
<option value="{{ $quantityunit->id }}">{{ $quantityunit->name }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a href="{{ $U('/products') }}" class="btn btn-success">{{ $L('OK') }}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@stop
|
@@ -12,6 +12,9 @@
|
|||||||
<a class="btn btn-outline-dark" href="{{ $U('/product/new') }}">
|
<a class="btn btn-outline-dark" href="{{ $U('/product/new') }}">
|
||||||
<i class="fas fa-plus"></i> {{ $L('Add') }}
|
<i class="fas fa-plus"></i> {{ $L('Add') }}
|
||||||
</a>
|
</a>
|
||||||
|
<a class="btn btn-outline-secondary" href="{{ $U('/productpresets') }}">
|
||||||
|
<i class="fas fa-sliders-h"></i> {{ $L('Presets for new products') }}
|
||||||
|
</a>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -50,7 +53,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ $product->name }}
|
{{ $product->name }}@if(!empty($product->picture_file_name)) <i class="fas fa-image text-muted"></i>@endif
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ FindObjectInArrayByPropertyValue($locations, 'id', $product->location_id)->name }}
|
{{ FindObjectInArrayByPropertyValue($locations, 'id', $product->location_id)->name }}
|
||||||
|
@@ -11,10 +11,13 @@
|
|||||||
@push('pageScripts')
|
@push('pageScripts')
|
||||||
<script src="{{ $U('/node_modules/summernote/dist/summernote-bs4.js?v=', true) }}{{ $version }}"></script>
|
<script src="{{ $U('/node_modules/summernote/dist/summernote-bs4.js?v=', true) }}{{ $version }}"></script>
|
||||||
@if(!empty($L('summernote_locale')))<script src="{{ $U('/node_modules', true) }}/summernote/dist/lang/summernote-{{ $L('summernote_locale') }}.js?v={{ $version }}"></script>@endif
|
@if(!empty($L('summernote_locale')))<script src="{{ $U('/node_modules', true) }}/summernote/dist/lang/summernote-{{ $L('summernote_locale') }}.js?v={{ $version }}"></script>@endif
|
||||||
|
<script src="{{ $U('/node_modules/datatables.net-rowgroup/js/dataTables.rowGroup.min.js?v=', true) }}{{ $version }}"></script>
|
||||||
|
<script src="{{ $U('/node_modules/datatables.net-rowgroup-bs4/js/rowGroup.bootstrap4.min.js?v=', true) }}{{ $version }}"></script>
|
||||||
@endpush
|
@endpush
|
||||||
|
|
||||||
@push('pageStyles')
|
@push('pageStyles')
|
||||||
<link href="{{ $U('/node_modules/summernote/dist/summernote-bs4.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
<link href="{{ $U('/node_modules/summernote/dist/summernote-bs4.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||||
|
<link href="{{ $U('/node_modules/datatables.net-rowgroup-bs4/css/rowGroup.bootstrap4.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||||
@endpush
|
@endpush
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
@@ -51,53 +54,129 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-xs-12 col-md-5 pb-3">
|
<div class="col-xs-12 col-md-5 pb-3">
|
||||||
<h2>
|
<div class="row">
|
||||||
{{ $L('Ingredients list') }}
|
<div class="col">
|
||||||
<a id="recipe-pos-add-button" class="btn btn-outline-dark" href="#">
|
<h2>
|
||||||
<i class="fas fa-plus"></i> {{ $L('Add') }}
|
{{ $L('Ingredients list') }}
|
||||||
</a>
|
<a id="recipe-pos-add-button" class="btn btn-outline-dark" href="#">
|
||||||
</h1>
|
<i class="fas fa-plus"></i> {{ $L('Add') }}
|
||||||
<table id="recipes-pos-table" class="table table-sm table-striped dt-responsive">
|
</a>
|
||||||
<thead>
|
</h2>
|
||||||
<tr>
|
<table id="recipes-pos-table" class="table table-sm table-striped dt-responsive">
|
||||||
<th>#</th>
|
<thead>
|
||||||
<th>{{ $L('Product') }}</th>
|
<tr>
|
||||||
<th>{{ $L('Amount') }}</th>
|
<th>#</th>
|
||||||
<th>{{ $L('Note') }}</th>
|
<th>{{ $L('Product') }}</th>
|
||||||
</tr>
|
<th>{{ $L('Amount') }}</th>
|
||||||
</thead>
|
<th>{{ $L('Note') }}</th>
|
||||||
<tbody>
|
<th class="d-none">Hiden ingredient group</th>
|
||||||
@if($mode == "edit")
|
</tr>
|
||||||
@foreach($recipePositions as $recipePosition)
|
</thead>
|
||||||
<tr class="@if(FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $recipePosition->id)->need_fulfilled == 1) table-success @elseif(FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $recipePosition->id)->need_fulfilled_with_shopping_list == 1) table-warning @else table-danger @endif">
|
<tbody>
|
||||||
<td class="fit-content">
|
@if($mode == "edit")
|
||||||
<a class="btn btn-sm btn-info recipe-pos-edit-button" href="#" data-recipe-pos-id="{{ $recipePosition->id }}">
|
@foreach($recipePositions as $recipePosition)
|
||||||
<i class="fas fa-edit"></i>
|
<tr class="@if(FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $recipePosition->id)->need_fulfilled == 1) table-success @elseif(FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $recipePosition->id)->need_fulfilled_with_shopping_list == 1) table-warning @else table-danger @endif">
|
||||||
</a>
|
<td class="fit-content">
|
||||||
<a class="btn btn-sm btn-danger recipe-pos-delete-button" href="#" data-recipe-pos-id="{{ $recipePosition->id }}" data-recipe-pos-name="{{ FindObjectInArrayByPropertyValue($products, 'id', $recipePosition->product_id)->name }}">
|
<a class="btn btn-sm btn-info recipe-pos-edit-button" href="#" data-recipe-pos-id="{{ $recipePosition->id }}">
|
||||||
<i class="fas fa-trash"></i>
|
<i class="fas fa-edit"></i>
|
||||||
</a>
|
</a>
|
||||||
<a class="btn btn-sm btn-primary recipe-pos-order-missing-button @if(FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $recipePosition->id)->need_fulfilled_with_shopping_list == 1){{ disabled }}@endif" href="#" data-toggle="tooltip" data-placement="right" title="{{ $L('Put missing amount on shopping list') }}" data-recipe-name="{{ $recipe->name }}" data-product-id="{{ $recipePosition->product_id }}" data-product-amount="{{ FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $recipePosition->id)->missing_amount }}" data-product-name="{{ FindObjectInArrayByPropertyValue($products, 'id', $recipePosition->product_id)->name }}">
|
<a class="btn btn-sm btn-danger recipe-pos-delete-button" href="#" data-recipe-pos-id="{{ $recipePosition->id }}" data-recipe-pos-name="{{ FindObjectInArrayByPropertyValue($products, 'id', $recipePosition->product_id)->name }}">
|
||||||
<i class="fas fa-cart-plus"></i>
|
<i class="fas fa-trash"></i>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
<a class="btn btn-sm btn-primary recipe-pos-order-missing-button @if(FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $recipePosition->id)->need_fulfilled_with_shopping_list == 1){{ disabled }}@endif" href="#" data-toggle="tooltip" data-placement="right" title="{{ $L('Put missing amount on shopping list') }}" data-recipe-name="{{ $recipe->name }}" data-product-id="{{ $recipePosition->product_id }}" data-product-amount="{{ FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $recipePosition->id)->missing_amount }}" data-product-name="{{ FindObjectInArrayByPropertyValue($products, 'id', $recipePosition->product_id)->name }}">
|
||||||
<td>
|
<i class="fas fa-cart-plus"></i>
|
||||||
{{ FindObjectInArrayByPropertyValue($products, 'id', $recipePosition->product_id)->name }}
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ $recipePosition->amount }} {{ Pluralize($recipePosition->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', $recipePosition->qu_id)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', $recipePosition->qu_id)->name_plural) }}
|
{{ FindObjectInArrayByPropertyValue($products, 'id', $recipePosition->product_id)->name }}
|
||||||
<span class="timeago-contextual">@if(FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $recipePosition->id)->need_fulfilled == 1) {{ $L('Enough in stock') }} @else {{ $L('Not enough in stock, #1 missing, #2 already on shopping list', FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $recipePosition->id)->missing_amount, FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $recipePosition->id)->amount_on_shopping_list) }} @endif</span>
|
</td>
|
||||||
</td>
|
<td>
|
||||||
<td class="fit-content">
|
{{ $recipePosition->amount }} {{ Pluralize($recipePosition->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', $recipePosition->qu_id)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', $recipePosition->qu_id)->name_plural) }}
|
||||||
<a class="btn btn-sm btn-info recipe-pos-show-note-button @if(empty($recipePosition->note)) disabled @endif" href="#" data-toggle="tooltip" data-placement="top" title="{{ $L('Show notes') }}" data-recipe-pos-note="{{ $recipePosition->note }}">
|
<span class="timeago-contextual">@if(FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $recipePosition->id)->need_fulfilled == 1) {{ $L('Enough in stock') }} @else {{ $L('Not enough in stock, #1 missing, #2 already on shopping list', FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $recipePosition->id)->missing_amount, FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $recipePosition->id)->amount_on_shopping_list) }} @endif</span>
|
||||||
<i class="fas fa-eye"></i>
|
</td>
|
||||||
</a>
|
<td class="fit-content">
|
||||||
</td>
|
<a class="btn btn-sm btn-info recipe-pos-show-note-button @if(empty($recipePosition->note)) disabled @endif" href="#" data-toggle="tooltip" data-placement="top" title="{{ $L('Show notes') }}" data-recipe-pos-note="{{ $recipePosition->note }}">
|
||||||
</tr>
|
<i class="fas fa-eye"></i>
|
||||||
@endforeach
|
</a>
|
||||||
@endif
|
</td>
|
||||||
</tbody>
|
<td>
|
||||||
</table>
|
{{ $recipePosition->ingredient_group }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
@endif
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mt-5">
|
||||||
|
<div class="col">
|
||||||
|
<h2>
|
||||||
|
{{ $L('Included recipes') }}
|
||||||
|
<a id="recipe-include-add-button" class="btn btn-outline-dark" href="#">
|
||||||
|
<i class="fas fa-plus"></i> {{ $L('Add') }}
|
||||||
|
</a>
|
||||||
|
</h2>
|
||||||
|
<table id="recipes-includes-table" class="table table-sm table-striped dt-responsive">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>{{ $L('Recipe') }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@if($mode == "edit")
|
||||||
|
@foreach($recipeNestings as $recipeNesting)
|
||||||
|
<tr>
|
||||||
|
<td class="fit-content">
|
||||||
|
<a class="btn btn-sm btn-info recipe-include-edit-button" href="#" data-recipe-include-id="{{ $recipeNesting->id }}" data-recipe-included-recipe-id="{{ $recipeNesting->includes_recipe_id }}">
|
||||||
|
<i class="fas fa-edit"></i>
|
||||||
|
</a>
|
||||||
|
<a class="btn btn-sm btn-danger recipe-include-delete-button" href="#" data-recipe-include-id="{{ $recipeNesting->id }}" data-recipe-include-name="{{ FindObjectInArrayByPropertyValue($recipes, 'id', $recipeNesting->includes_recipe_id)->name }}">
|
||||||
|
<i class="fas fa-trash"></i>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ FindObjectInArrayByPropertyValue($recipes, 'id', $recipeNesting->includes_recipe_id)->name }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
@endif
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal fade" id="recipe-include-editform-modal" tabindex="-1">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content text-center">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h4 id="recipe-include-editform-title" class="modal-title w-100"></h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form id="recipe-include-form" novalidate>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="includes_recipe_id">{{ $L('Recipe') }}</label>
|
||||||
|
<select required class="form-control" id="includes_recipe_id" name="includes_recipe_id">
|
||||||
|
<option></option>
|
||||||
|
@foreach($recipes as $recipeForList)
|
||||||
|
@if($recipeForList->id !== $recipe->id)
|
||||||
|
<option data-already-included="{{ BoolToString(FindObjectInArrayByPropertyValue($recipeNestings, 'includes_recipe_id', $recipeForList->id) === null) }}" value="{{ $recipeForList->id }}">{{ $recipeForList->name }}</option>
|
||||||
|
@endif
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
<div class="invalid-feedback">{{ $L('A recipe is required') }}</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">{{ $L('Cancel') }}</button>
|
||||||
|
<button id="save-recipe-include-button" data-dismiss="modal" class="btn btn-success">{{ $L('Save') }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@stop
|
@stop
|
||||||
|
@@ -68,6 +68,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="ingredient_group">{{ $L('Group') }} <span class="small text-muted">{{ $L('This will be used as a headline to group ingredients together') }}</span></label>
|
||||||
|
<input type="text" class="form-control" id="ingredient_group" name="ingredient_group" value="@if($mode == 'edit'){{ $recipePos->ingredient_group }}@endif">
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="note">{{ $L('Note') }}</label>
|
<label for="note">{{ $L('Note') }}</label>
|
||||||
<textarea class="form-control" rows="2" id="note" name="note">@if($mode == 'edit'){{ $recipePos->note }}@endif</textarea>
|
<textarea class="form-control" rows="2" id="note" name="note">@if($mode == 'edit'){{ $recipePos->note }}@endif</textarea>
|
||||||
|
@@ -62,25 +62,73 @@
|
|||||||
<i class="fas fa-expand-arrows-alt"></i>
|
<i class="fas fa-expand-arrows-alt"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Subrecipes first -->
|
||||||
|
@foreach($selectedRecipeSubRecipes as $selectedRecipeSubRecipe)
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="mb-0">{{ $selectedRecipeSubRecipe->name }}</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@php $selectedRecipeSubRecipePositionsFiltered = FindAllObjectsInArrayByPropertyValue($selectedRecipeSubRecipesPositions, 'recipe_id', $selectedRecipeSubRecipe->id); @endphp
|
||||||
|
@if(count($selectedRecipeSubRecipePositionsFiltered) > 0)
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="mb-0">{{ $L('Ingredients') }}</h5>
|
||||||
|
</div>
|
||||||
|
<ul class="list-group list-group-flush">
|
||||||
|
@php $lastGroup = 'undefined'; @endphp
|
||||||
|
@foreach($selectedRecipeSubRecipePositionsFiltered as $selectedRecipePosition)
|
||||||
|
@if($lastGroup != $selectedRecipePosition->ingredient_group)
|
||||||
|
<h5 class="mb-2 mt-2 ml-4"><strong>{{ $selectedRecipePosition->ingredient_group }}</strong></h5>
|
||||||
|
@endif
|
||||||
|
<li class="list-group-item">
|
||||||
|
{{ $selectedRecipePosition->amount }} {{ Pluralize($selectedRecipePosition->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', $selectedRecipePosition->qu_id)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', $selectedRecipePosition->qu_id)->name_plural) }} {{ FindObjectInArrayByPropertyValue($products, 'id', $selectedRecipePosition->product_id)->name }}
|
||||||
|
<span class="timeago-contextual">@if(FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $selectedRecipePosition->id)->need_fulfilled == 1) {{ $L('Enough in stock') }} @else {{ $L('Not enough in stock, #1 missing, #2 already on shopping list', FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $selectedRecipePosition->id)->missing_amount, FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $selectedRecipePosition->id)->amount_on_shopping_list) }} @endif</span>
|
||||||
|
|
||||||
|
@if(!empty($selectedRecipePosition->note))
|
||||||
|
<div class="text-muted">{!! nl2br($selectedRecipePosition->note) !!}</div>
|
||||||
|
@endif
|
||||||
|
</li>
|
||||||
|
@php $lastGroup = $selectedRecipePosition->ingredient_group; @endphp
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
@endif
|
||||||
|
@if(!empty($selectedRecipeSubRecipe->description))
|
||||||
|
<div class="card-body">
|
||||||
|
<h5>{{ $L('Preparation') }}</h5>
|
||||||
|
{!! $selectedRecipeSubRecipe->description !!}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
<!-- Selected recipe -->
|
||||||
|
@if($selectedRecipePositions->count() > 0)
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="mb-0">{{ $L('Ingredients') }}</h5>
|
<h5 class="mb-0">{{ $L('Ingredients') }}</h5>
|
||||||
</div>
|
</div>
|
||||||
<ul class="list-group list-group-flush">
|
<ul class="list-group list-group-flush">
|
||||||
|
@php $lastGroup = 'undefined'; @endphp
|
||||||
@foreach($selectedRecipePositions as $selectedRecipePosition)
|
@foreach($selectedRecipePositions as $selectedRecipePosition)
|
||||||
|
@if($lastGroup != $selectedRecipePosition->ingredient_group)
|
||||||
|
<h5 class="mb-2 mt-2 ml-4"><strong>{{ $selectedRecipePosition->ingredient_group }}</strong></h5>
|
||||||
|
@endif
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
{{ $selectedRecipePosition->amount }} {{ Pluralize($selectedRecipePosition->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', $selectedRecipePosition->qu_id)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', $selectedRecipePosition->qu_id)->name_plural) }} {{ FindObjectInArrayByPropertyValue($products, 'id', $selectedRecipePosition->product_id)->name }}
|
{{ $selectedRecipePosition->amount }} {{ Pluralize($selectedRecipePosition->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', $selectedRecipePosition->qu_id)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', $selectedRecipePosition->qu_id)->name_plural) }} {{ FindObjectInArrayByPropertyValue($products, 'id', $selectedRecipePosition->product_id)->name }}
|
||||||
<span class="timeago-contextual">@if(FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $selectedRecipePosition->id)->need_fulfilled == 1) {{ $L('Enough in stock') }} @else {{ $L('Not enough in stock, #1 missing, #2 already on shopping list', FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $selectedRecipePosition->id)->missing_amount, FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $selectedRecipePosition->id)->amount_on_shopping_list) }} @endif</span>
|
<span class="timeago-contextual">@if(FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $selectedRecipePosition->id)->need_fulfilled == 1) {{ $L('Enough in stock') }} @else {{ $L('Not enough in stock, #1 missing, #2 already on shopping list', FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $selectedRecipePosition->id)->missing_amount, FindObjectInArrayByPropertyValue($recipesFulfillment, 'recipe_pos_id', $selectedRecipePosition->id)->amount_on_shopping_list) }} @endif</span>
|
||||||
|
|
||||||
@if(!empty($selectedRecipePosition->note))
|
@if(!empty($selectedRecipePosition->note))
|
||||||
<div class="text-muted">{{ $selectedRecipePosition->note }} </div>
|
<div class="text-muted">{!! nl2br($selectedRecipePosition->note) !!}</div>
|
||||||
@endif
|
@endif
|
||||||
</li>
|
</li>
|
||||||
|
@php $lastGroup = $selectedRecipePosition->ingredient_group; @endphp
|
||||||
@endforeach
|
@endforeach
|
||||||
</ul>
|
</ul>
|
||||||
|
@endif
|
||||||
|
@if(!empty($selectedRecipe->description))
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5>{{ $L('Preparation') }}</h5>
|
<h5>{{ $L('Preparation') }}</h5>
|
||||||
{!! $selectedRecipe->description !!}
|
{!! $selectedRecipe->description !!}
|
||||||
</div>
|
</div>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
@@ -71,7 +71,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@if(!empty($listItem->product_id)) {{ FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->name }}<br>@endif<em>{{ $listItem->note }}</em>
|
@if(!empty($listItem->product_id)) {{ FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->name }}<br>@endif<em>{!! nl2br($listItem->note) !!}</em>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ $listItem->amount + $listItem->amount_autoadded }} @if(!empty($listItem->product_id)){{ Pluralize($listItem->amount + $listItem->amount_autoadded, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->qu_id_purchase)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->qu_id_purchase)->name_plural) }}@endif
|
{{ $listItem->amount + $listItem->amount_autoadded }} @if(!empty($listItem->product_id)){{ Pluralize($listItem->amount + $listItem->amount_autoadded, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->qu_id_purchase)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $listItem->product_id)->qu_id_purchase)->name_plural) }}@endif
|
||||||
|
74
views/stockjournal.blade.php
Normal file
74
views/stockjournal.blade.php
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
@extends('layout.default')
|
||||||
|
|
||||||
|
@section('title', $L('Stock journal'))
|
||||||
|
@section('activeNav', 'stockjournal')
|
||||||
|
@section('viewJsName', 'stockjournal')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h1>@yield('title')</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row my-3">
|
||||||
|
<div class="col-xs-12 col-md-6 col-xl-3">
|
||||||
|
<label for="product-filter">{{ $L('Filter by product') }}</label> <i class="fas fa-filter"></i>
|
||||||
|
<select class="form-control" id="product-filter">
|
||||||
|
<option value="all">{{ $L('All') }}</option>
|
||||||
|
@foreach($products as $product)
|
||||||
|
<option value="{{ $product->id }}">{{ $product->name }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-12 col-md-6 col-xl-3">
|
||||||
|
<label for="search">{{ $L('Search') }}</label> <i class="fas fa-search"></i>
|
||||||
|
<input type="text" class="form-control" id="search">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<table id="stock-journal-table" class="table table-sm table-striped dt-responsive">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>{{ $L('Product') }}</th>
|
||||||
|
<th>{{ $L('Amount') }}</th>
|
||||||
|
<th>{{ $L('Booking time') }}</th>
|
||||||
|
<th>{{ $L('Booking type') }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach($stockLog as $stockLogEntry)
|
||||||
|
<tr class="@if($stockLogEntry->undone == 1) text-muted @endif">
|
||||||
|
<td class="fit-content">
|
||||||
|
<a class="btn btn-secondary btn-sm undo-stock-booking-button @if($stockLogEntry->undone == 1) disabled @endif" href="#" data-booking-id="{{ $stockLogEntry->id }}" data-toggle="tooltip" data-placement="left" title="{{ $L('Undo booking') }}">
|
||||||
|
<i class="fas fa-undo"></i>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="@if($stockLogEntry->undone == 1) text-strike-through @endif">{{ FindObjectInArrayByPropertyValue($products, 'id', $stockLogEntry->product_id)->name }}</span>
|
||||||
|
@if($stockLogEntry->undone == 1)
|
||||||
|
<br>
|
||||||
|
{{ $L('Undone on') . ' ' . $stockLogEntry->undone_timestamp }}
|
||||||
|
<time class="timeago timeago-contextual" datetime="{{ $stockLogEntry->undone_timestamp }}"></time>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ $stockLogEntry->amount }} {{ Pluralize($stockLogEntry->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $stockLogEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $stockLogEntry->product_id)->qu_id_stock)->name_plural) }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ $stockLogEntry->row_created_timestamp }}
|
||||||
|
<time class="timeago timeago-contextual" datetime="{{ $stockLogEntry->row_created_timestamp }}"></time>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ $L($stockLogEntry->transaction_type) }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@stop
|
@@ -19,7 +19,12 @@
|
|||||||
@section('content')
|
@section('content')
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h1>@yield('title') <small id="info-current-stock" class="text-muted"></small></h1>
|
<h1>@yield('title')
|
||||||
|
<small id="info-current-stock" class="text-muted"></small>
|
||||||
|
<a class="btn btn-outline-dark responsive-button" href="{{ $U('/stockjournal') }}">
|
||||||
|
<i class="fas fa-file-alt"></i> {{ $L('Journal') }}
|
||||||
|
</a>
|
||||||
|
</h1>
|
||||||
<p id="info-expiring-products" data-next-x-days="{{ $nextXDays }}" data-status-filter="expiring" class="btn btn-lg btn-warning status-filter-button responsive-button mr-2"></p>
|
<p id="info-expiring-products" data-next-x-days="{{ $nextXDays }}" data-status-filter="expiring" class="btn btn-lg btn-warning status-filter-button responsive-button mr-2"></p>
|
||||||
<p id="info-expired-products" data-status-filter="expired" class="btn btn-lg btn-danger status-filter-button responsive-button mr-2"></p>
|
<p id="info-expired-products" data-status-filter="expired" class="btn btn-lg btn-danger status-filter-button responsive-button mr-2"></p>
|
||||||
<p id="info-missing-products" data-status-filter="belowminstockamount" class="btn btn-lg btn-info status-filter-button responsive-button"></p>
|
<p id="info-missing-products" data-status-filter="belowminstockamount" class="btn btn-lg btn-info status-filter-button responsive-button"></p>
|
||||||
@@ -36,6 +41,15 @@
|
|||||||
@endforeach
|
@endforeach
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-xs-12 col-md-6 col-xl-3">
|
||||||
|
<label for="location-filter">{{ $L('Filter by product group') }}</label> <i class="fas fa-filter"></i>
|
||||||
|
<select class="form-control" id="product-group-filter">
|
||||||
|
<option value="all">{{ $L('All') }}</option>
|
||||||
|
@foreach($productGroups as $productGroup)
|
||||||
|
<option value="{{ $productGroup->name }}">{{ $productGroup->name }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="col-xs-12 col-md-6 col-xl-3">
|
<div class="col-xs-12 col-md-6 col-xl-3">
|
||||||
<label for="status-filter">{{ $L('Filter by status') }}</label> <i class="fas fa-filter"></i>
|
<label for="status-filter">{{ $L('Filter by status') }}</label> <i class="fas fa-filter"></i>
|
||||||
<select class="form-control" id="status-filter">
|
<select class="form-control" id="status-filter">
|
||||||
@@ -62,11 +76,12 @@
|
|||||||
<th>{{ $L('Next best before date') }}</th>
|
<th>{{ $L('Next best before date') }}</th>
|
||||||
<th class="d-none">Hidden location</th>
|
<th class="d-none">Hidden location</th>
|
||||||
<th class="d-none">Hidden status</th>
|
<th class="d-none">Hidden status</th>
|
||||||
|
<th class="d-none">Hidden product group</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@foreach($currentStock as $currentStockEntry)
|
@foreach($currentStock as $currentStockEntry)
|
||||||
<tr id="product-{{ $currentStockEntry->product_id }}-row" class="@if($currentStockEntry->best_before_date < date('Y-m-d', strtotime('-1 days')) && $currentStockEntry->amount > 0) table-danger @elseif($currentStockEntry->best_before_date < date('Y-m-d', strtotime("+$nextXDays days")) && $currentStockEntry->amount > 0) table-warning @elseif (FindObjectInArrayByPropertyValue($missingProducts, 'id', $currentStockEntry->product_id) !== null) table-info @endif">
|
<tr id="product-{{ $currentStockEntry->product_id }}-row" class="@if($currentStockEntry->best_before_date < date('Y-m-d 23:59:59', strtotime('-1 days')) && $currentStockEntry->amount > 0) table-danger @elseif($currentStockEntry->best_before_date < date('Y-m-d 23:59:59', strtotime("+$nextXDays days")) && $currentStockEntry->amount > 0) table-warning @elseif (FindObjectInArrayByPropertyValue($missingProducts, 'id', $currentStockEntry->product_id) !== null) table-info @endif">
|
||||||
<td class="fit-content">
|
<td class="fit-content">
|
||||||
<a class="btn btn-success btn-sm product-consume-button @if($currentStockEntry->amount == 0) disabled @endif" href="#" data-toggle="tooltip" data-placement="left" title="{{ $L('Consume #3 #1 of #2', FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name, 1) }}"
|
<a class="btn btn-success btn-sm product-consume-button @if($currentStockEntry->amount == 0) disabled @endif" href="#" data-toggle="tooltip" data-placement="left" title="{{ $L('Consume #3 #1 of #2', FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name, 1) }}"
|
||||||
data-product-id="{{ $currentStockEntry->product_id }}"
|
data-product-id="{{ $currentStockEntry->product_id }}"
|
||||||
@@ -82,26 +97,29 @@
|
|||||||
data-consume-amount="{{ $currentStockEntry->amount }}">
|
data-consume-amount="{{ $currentStockEntry->amount }}">
|
||||||
<i class="fas fa-utensils"></i> {{ $L('All') }}
|
<i class="fas fa-utensils"></i> {{ $L('All') }}
|
||||||
</a>
|
</a>
|
||||||
|
<a class="btn btn-info btn-sm" href="{{ $U('/stockjournal?product=') }}{{ $currentStockEntry->product_id }}">
|
||||||
|
<i class="fas fa-file-alt"></i>
|
||||||
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td class="product-name-cell"
|
<td class="product-name-cell" data-product-id="{{ $currentStockEntry->product_id }}">
|
||||||
data-picture-url="{{ $U('/api/file/productpictures?file_name=' . FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->picture_file_name) }}"
|
{{ FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name }} <i class="fas fa-info text-muted"></i>
|
||||||
data-product-id="{{ $currentStockEntry->product_id }}"
|
|
||||||
data-product-name="{{ FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name }}"
|
|
||||||
data-product-has-picture="{{ BoolToString(!empty(FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->picture_file_name)) }}">
|
|
||||||
{{ FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name }}@if(!empty(FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->picture_file_name)) <i class="fas fa-image text-muted"></i>@endif
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span id="product-{{ $currentStockEntry->product_id }}-amount">{{ $currentStockEntry->amount }}</span> {{ Pluralize($currentStockEntry->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name_plural) }}
|
<span id="product-{{ $currentStockEntry->product_id }}-amount">{{ $currentStockEntry->amount }}</span> {{ Pluralize($currentStockEntry->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name_plural) }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span id="product-{{ $currentStockEntry->product_id }}-next-best-before-date">{{ $currentStockEntry->best_before_date }}</span>
|
<span id="product-{{ $currentStockEntry->product_id }}-next-best-before-date">{{ $currentStockEntry->best_before_date }}</span>
|
||||||
<time id="product-{{ $currentStockEntry->product_id }}-next-best-before-date-timeago" class="timeago timeago-contextual" datetime="{{ $currentStockEntry->best_before_date }}"></time>
|
<time id="product-{{ $currentStockEntry->product_id }}-next-best-before-date-timeago" class="timeago timeago-contextual" datetime="{{ $currentStockEntry->best_before_date }} 23:59:59"></time>
|
||||||
</td>
|
</td>
|
||||||
<td class="d-none">
|
<td class="d-none">
|
||||||
{{ FindObjectInArrayByPropertyValue($locations, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->location_id)->name }}
|
{{ FindObjectInArrayByPropertyValue($locations, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->location_id)->name }}
|
||||||
</td>
|
</td>
|
||||||
<td class="d-none">
|
<td class="d-none">
|
||||||
@if($currentStockEntry->best_before_date < date('Y-m-d', strtotime('-1 days')) && $currentStockEntry->amount > 0) expired @elseif($currentStockEntry->best_before_date < date('Y-m-d', strtotime("+$nextXDays days")) && $currentStockEntry->amount > 0) expiring @elseif (FindObjectInArrayByPropertyValue($missingProducts, 'id', $currentStockEntry->product_id) !== null) belowminstockamount @endif
|
@if($currentStockEntry->best_before_date < date('Y-m-d 23:59:59', strtotime('-1 days')) && $currentStockEntry->amount > 0) expired @elseif($currentStockEntry->best_before_date < date('Y-m-d 23:59:59', strtotime("+$nextXDays days")) && $currentStockEntry->amount > 0) expiring @elseif (FindObjectInArrayByPropertyValue($missingProducts, 'id', $currentStockEntry->product_id) !== null) belowminstockamount @endif
|
||||||
|
</td>
|
||||||
|
@php $productGroup = FindObjectInArrayByPropertyValue($productGroups, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->product_group_id) @endphp
|
||||||
|
<td class="d-none">
|
||||||
|
@if($productGroup !== null){{ $productGroup->name }}@endif
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
@@ -109,4 +127,17 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="modal fade" id="stockoverview-productcard-modal" tabindex="-1">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content text-center">
|
||||||
|
<div class="modal-body">
|
||||||
|
@include('components.productcard')
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{ $L('Close') }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@stop
|
@stop
|
||||||
|
55
yarn.lock
55
yarn.lock
@@ -7,8 +7,9 @@
|
|||||||
resolved "https://github.com/berrnd/bootstrap-combobox.git#fcf0110146f4daab94888234c57d198b4ca5f129"
|
resolved "https://github.com/berrnd/bootstrap-combobox.git#fcf0110146f4daab94888234c57d198b4ca5f129"
|
||||||
|
|
||||||
"@fortawesome/fontawesome-free@^5.1.0":
|
"@fortawesome/fontawesome-free@^5.1.0":
|
||||||
version "5.3.1"
|
version "5.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.3.1.tgz#5466b8f31c1f493a96754c1426c25796d0633dd9"
|
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.4.2.tgz#b2d782da69c45ea61954291e2615a8f7741c96b2"
|
||||||
|
integrity sha512-lpruVv/4AkKUujyzHCNJ8yOceBf7Na/pFaX52ZI/BFMCYkUEwiQ1P0viZg//+WelrNNEgvMOvCMDEDaOMZ/u1w==
|
||||||
|
|
||||||
"TagManager@https://github.com/max-favilli/tagmanager.git#3.0.2":
|
"TagManager@https://github.com/max-favilli/tagmanager.git#3.0.2":
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
@@ -23,21 +24,25 @@
|
|||||||
bootstrap@4.0.0:
|
bootstrap@4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.0.0.tgz#ceb03842c145fcc1b9b4e15da2a05656ba68469a"
|
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.0.0.tgz#ceb03842c145fcc1b9b4e15da2a05656ba68469a"
|
||||||
|
integrity sha512-gulJE5dGFo6Q61V/whS6VM4WIyrlydXfCgkE+Gxe5hjrJ8rXLLZlALq7zq2RPhOc45PSwQpJkrTnc2KgD6cvmA==
|
||||||
|
|
||||||
bootstrap@>=4.1.2, bootstrap@^4.1.1:
|
bootstrap@>=4.1.2, bootstrap@^4.1.1:
|
||||||
version "4.1.3"
|
version "4.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.1.3.tgz#0eb371af2c8448e8c210411d0cb824a6409a12be"
|
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.1.3.tgz#0eb371af2c8448e8c210411d0cb824a6409a12be"
|
||||||
|
integrity sha512-rDFIzgXcof0jDyjNosjv4Sno77X4KuPeFxG2XZZv1/Kc8DRVGVADdoQyyOVDwPqL36DDmtCQbrpMCqvpPLJQ0w==
|
||||||
|
|
||||||
chart.js@2.7.1:
|
chart.js@2.7.1:
|
||||||
version "2.7.1"
|
version "2.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.7.1.tgz#ae90b4aa4ff1f02decd6b1a2a8dabfd73c9f9886"
|
resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.7.1.tgz#ae90b4aa4ff1f02decd6b1a2a8dabfd73c9f9886"
|
||||||
|
integrity sha512-pX1oQAY86MiuyZ2hY593Acbl4MLHKrBBhhmZ1YqSadzQbbsBE2rnd6WISoHjIsdf0WDeC0hbePYCz2ZxkV8L+g==
|
||||||
dependencies:
|
dependencies:
|
||||||
chartjs-color "~2.2.0"
|
chartjs-color "~2.2.0"
|
||||||
moment "~2.18.0"
|
moment "~2.18.0"
|
||||||
|
|
||||||
chart.js@^2.7.2:
|
chart.js@^2.7.2:
|
||||||
version "2.7.2"
|
version "2.7.3"
|
||||||
resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.7.2.tgz#3c9fde4dc5b95608211bdefeda7e5d33dffa5714"
|
resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.7.3.tgz#cdb61618830bf216dc887e2f7b1b3c228b73c57e"
|
||||||
|
integrity sha512-3+7k/DbR92m6BsMUYP6M0dMsMVZpMnwkUyNSAbqolHKsbIzH2Q4LWVEHHYq7v0fmEV8whXE0DrjANulw9j2K5g==
|
||||||
dependencies:
|
dependencies:
|
||||||
chartjs-color "^2.1.0"
|
chartjs-color "^2.1.0"
|
||||||
moment "^2.10.2"
|
moment "^2.10.2"
|
||||||
@@ -45,12 +50,14 @@ chart.js@^2.7.2:
|
|||||||
chartjs-color-string@^0.5.0:
|
chartjs-color-string@^0.5.0:
|
||||||
version "0.5.0"
|
version "0.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/chartjs-color-string/-/chartjs-color-string-0.5.0.tgz#8d3752d8581d86687c35bfe2cb80ac5213ceb8c1"
|
resolved "https://registry.yarnpkg.com/chartjs-color-string/-/chartjs-color-string-0.5.0.tgz#8d3752d8581d86687c35bfe2cb80ac5213ceb8c1"
|
||||||
|
integrity sha512-amWNvCOXlOUYxZVDSa0YOab5K/lmEhbFNKI55PWc4mlv28BDzA7zaoQTGxSBgJMHIW+hGX8YUrvw/FH4LyhwSQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
color-name "^1.0.0"
|
color-name "^1.0.0"
|
||||||
|
|
||||||
chartjs-color@^2.1.0, chartjs-color@~2.2.0:
|
chartjs-color@^2.1.0, chartjs-color@~2.2.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/chartjs-color/-/chartjs-color-2.2.0.tgz#84a2fb755787ed85c39dd6dd8c7b1d88429baeae"
|
resolved "https://registry.yarnpkg.com/chartjs-color/-/chartjs-color-2.2.0.tgz#84a2fb755787ed85c39dd6dd8c7b1d88429baeae"
|
||||||
|
integrity sha1-hKL7dVeH7YXDndbdjHsdiEKbrq4=
|
||||||
dependencies:
|
dependencies:
|
||||||
chartjs-color-string "^0.5.0"
|
chartjs-color-string "^0.5.0"
|
||||||
color-convert "^0.5.3"
|
color-convert "^0.5.3"
|
||||||
@@ -58,14 +65,17 @@ chartjs-color@^2.1.0, chartjs-color@~2.2.0:
|
|||||||
color-convert@^0.5.3:
|
color-convert@^0.5.3:
|
||||||
version "0.5.3"
|
version "0.5.3"
|
||||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-0.5.3.tgz#bdb6c69ce660fadffe0b0007cc447e1b9f7282bd"
|
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-0.5.3.tgz#bdb6c69ce660fadffe0b0007cc447e1b9f7282bd"
|
||||||
|
integrity sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=
|
||||||
|
|
||||||
color-name@^1.0.0:
|
color-name@^1.0.0:
|
||||||
version "1.1.4"
|
version "1.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||||
|
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||||
|
|
||||||
datatables.net-bs4@1.10.16:
|
datatables.net-bs4@1.10.16:
|
||||||
version "1.10.16"
|
version "1.10.16"
|
||||||
resolved "https://registry.yarnpkg.com/datatables.net-bs4/-/datatables.net-bs4-1.10.16.tgz#9eee67cfa8565bd3807a603a188305f7d0e20e32"
|
resolved "https://registry.yarnpkg.com/datatables.net-bs4/-/datatables.net-bs4-1.10.16.tgz#9eee67cfa8565bd3807a603a188305f7d0e20e32"
|
||||||
|
integrity sha1-nu5nz6hWW9OAemA6GIMF99DiDjI=
|
||||||
dependencies:
|
dependencies:
|
||||||
datatables.net "1.10.16"
|
datatables.net "1.10.16"
|
||||||
jquery ">=1.7"
|
jquery ">=1.7"
|
||||||
@@ -73,6 +83,7 @@ datatables.net-bs4@1.10.16:
|
|||||||
datatables.net-bs4@^1.10.15, datatables.net-bs4@^1.10.19:
|
datatables.net-bs4@^1.10.15, datatables.net-bs4@^1.10.19:
|
||||||
version "1.10.19"
|
version "1.10.19"
|
||||||
resolved "https://registry.yarnpkg.com/datatables.net-bs4/-/datatables.net-bs4-1.10.19.tgz#0608dff22008cf3c7b8a68b1bc702ed255b404fb"
|
resolved "https://registry.yarnpkg.com/datatables.net-bs4/-/datatables.net-bs4-1.10.19.tgz#0608dff22008cf3c7b8a68b1bc702ed255b404fb"
|
||||||
|
integrity sha512-pgeP17w4aPR7HIxIwuJghfqXULjdg1K6xMUUKDyCERJRSNNK4MRToFfELtIsluLNN555YBK4Kx8nihX5/ZT1Fw==
|
||||||
dependencies:
|
dependencies:
|
||||||
datatables.net "1.10.19"
|
datatables.net "1.10.19"
|
||||||
jquery ">=1.7"
|
jquery ">=1.7"
|
||||||
@@ -80,6 +91,7 @@ datatables.net-bs4@^1.10.15, datatables.net-bs4@^1.10.19:
|
|||||||
datatables.net-colreorder-bs4@^1.5.1:
|
datatables.net-colreorder-bs4@^1.5.1:
|
||||||
version "1.5.1"
|
version "1.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/datatables.net-colreorder-bs4/-/datatables.net-colreorder-bs4-1.5.1.tgz#7ded353a68296b85f0dbfb234b8cb5d8fc2bee3c"
|
resolved "https://registry.yarnpkg.com/datatables.net-colreorder-bs4/-/datatables.net-colreorder-bs4-1.5.1.tgz#7ded353a68296b85f0dbfb234b8cb5d8fc2bee3c"
|
||||||
|
integrity sha512-mi5wxkjnkI8fxGJ9e/Vu20E7MMZj7yK3xjLIzDrsHOHQupr6FF6eJnUoVH4gDo9Ynfb/yApVbnuW29v/YjnDKw==
|
||||||
dependencies:
|
dependencies:
|
||||||
datatables.net-bs4 "^1.10.15"
|
datatables.net-bs4 "^1.10.15"
|
||||||
datatables.net-colreorder "1.5.1"
|
datatables.net-colreorder "1.5.1"
|
||||||
@@ -88,6 +100,7 @@ datatables.net-colreorder-bs4@^1.5.1:
|
|||||||
datatables.net-colreorder@1.5.1, datatables.net-colreorder@^1.5.1:
|
datatables.net-colreorder@1.5.1, datatables.net-colreorder@^1.5.1:
|
||||||
version "1.5.1"
|
version "1.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/datatables.net-colreorder/-/datatables.net-colreorder-1.5.1.tgz#ee5eacd7178b5fd9396aab44d4907aae35086f8c"
|
resolved "https://registry.yarnpkg.com/datatables.net-colreorder/-/datatables.net-colreorder-1.5.1.tgz#ee5eacd7178b5fd9396aab44d4907aae35086f8c"
|
||||||
|
integrity sha512-nKV0ZBOdOG+CCrtDZZlTOvhu9NC53pr4rYR8Xhd3KIKipLZohWWdBoOFGMu+VKDvllg2Xj79oS/wicYSiNyteA==
|
||||||
dependencies:
|
dependencies:
|
||||||
datatables.net "^1.10.15"
|
datatables.net "^1.10.15"
|
||||||
jquery ">=1.7"
|
jquery ">=1.7"
|
||||||
@@ -95,6 +108,7 @@ datatables.net-colreorder@1.5.1, datatables.net-colreorder@^1.5.1:
|
|||||||
datatables.net-responsive-bs4@^2.2.3:
|
datatables.net-responsive-bs4@^2.2.3:
|
||||||
version "2.2.3"
|
version "2.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/datatables.net-responsive-bs4/-/datatables.net-responsive-bs4-2.2.3.tgz#639de17c1d31210ebf2b3c25f1c774c13f729e94"
|
resolved "https://registry.yarnpkg.com/datatables.net-responsive-bs4/-/datatables.net-responsive-bs4-2.2.3.tgz#639de17c1d31210ebf2b3c25f1c774c13f729e94"
|
||||||
|
integrity sha512-SQaWI0uLuPcaiBBin9zX+MuQfTSIkK1bYxbXqUV6NLkHCVa6PMQK7Rvftj0ywG4R7uOtjbzY8nSVqxEKvQI0Vg==
|
||||||
dependencies:
|
dependencies:
|
||||||
datatables.net-bs4 "^1.10.15"
|
datatables.net-bs4 "^1.10.15"
|
||||||
datatables.net-responsive "2.2.3"
|
datatables.net-responsive "2.2.3"
|
||||||
@@ -103,6 +117,7 @@ datatables.net-responsive-bs4@^2.2.3:
|
|||||||
datatables.net-responsive@2.2.3, datatables.net-responsive@^2.2.3:
|
datatables.net-responsive@2.2.3, datatables.net-responsive@^2.2.3:
|
||||||
version "2.2.3"
|
version "2.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/datatables.net-responsive/-/datatables.net-responsive-2.2.3.tgz#50a2b1b4955b16b32f573a3f00f473b0bfbee913"
|
resolved "https://registry.yarnpkg.com/datatables.net-responsive/-/datatables.net-responsive-2.2.3.tgz#50a2b1b4955b16b32f573a3f00f473b0bfbee913"
|
||||||
|
integrity sha512-8D6VtZcyuH3FG0Hn5A4LPZQEOX3+HrRFM7HjpmsQc/nQDBbdeBLkJX4Sh/o1nzFTSneuT1Wh/lYZHVPpjcN+Sw==
|
||||||
dependencies:
|
dependencies:
|
||||||
datatables.net "^1.10.15"
|
datatables.net "^1.10.15"
|
||||||
jquery ">=1.7"
|
jquery ">=1.7"
|
||||||
@@ -110,6 +125,7 @@ datatables.net-responsive@2.2.3, datatables.net-responsive@^2.2.3:
|
|||||||
datatables.net-rowgroup-bs4@^1.0.4:
|
datatables.net-rowgroup-bs4@^1.0.4:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/datatables.net-rowgroup-bs4/-/datatables.net-rowgroup-bs4-1.1.0.tgz#bcaa9842bc9cf70eeba19e8af6edad190c7b896e"
|
resolved "https://registry.yarnpkg.com/datatables.net-rowgroup-bs4/-/datatables.net-rowgroup-bs4-1.1.0.tgz#bcaa9842bc9cf70eeba19e8af6edad190c7b896e"
|
||||||
|
integrity sha512-R2C+lLbVyPuyITVJo/1va97nHOcQ06M0kReTmN4zaR4/SRkFDfOVXz48w2jT1AJW/j65DYAh+OHwUSYgcgKisA==
|
||||||
dependencies:
|
dependencies:
|
||||||
datatables.net-bs4 "^1.10.15"
|
datatables.net-bs4 "^1.10.15"
|
||||||
datatables.net-rowgroup "1.1.0"
|
datatables.net-rowgroup "1.1.0"
|
||||||
@@ -118,6 +134,7 @@ datatables.net-rowgroup-bs4@^1.0.4:
|
|||||||
datatables.net-rowgroup@1.1.0, datatables.net-rowgroup@^1.0.4:
|
datatables.net-rowgroup@1.1.0, datatables.net-rowgroup@^1.0.4:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/datatables.net-rowgroup/-/datatables.net-rowgroup-1.1.0.tgz#638efb37a1a15f5b3402b7dbce89b3bcdc286f1a"
|
resolved "https://registry.yarnpkg.com/datatables.net-rowgroup/-/datatables.net-rowgroup-1.1.0.tgz#638efb37a1a15f5b3402b7dbce89b3bcdc286f1a"
|
||||||
|
integrity sha512-OPIiiMTbIoh1hSnJ9lx3avqKpYtEPux5iA6jpWKRdyKbdYU8UQbi5ht3b096frYQplIuAQnQcwqpGmvrf77l6g==
|
||||||
dependencies:
|
dependencies:
|
||||||
datatables.net "^1.10.15"
|
datatables.net "^1.10.15"
|
||||||
jquery ">=1.7"
|
jquery ">=1.7"
|
||||||
@@ -125,6 +142,7 @@ datatables.net-rowgroup@1.1.0, datatables.net-rowgroup@^1.0.4:
|
|||||||
datatables.net-select-bs4@^1.2.7:
|
datatables.net-select-bs4@^1.2.7:
|
||||||
version "1.2.7"
|
version "1.2.7"
|
||||||
resolved "https://registry.yarnpkg.com/datatables.net-select-bs4/-/datatables.net-select-bs4-1.2.7.tgz#5e4ddd8feb412e974b54a15e81b2bb29840ba55b"
|
resolved "https://registry.yarnpkg.com/datatables.net-select-bs4/-/datatables.net-select-bs4-1.2.7.tgz#5e4ddd8feb412e974b54a15e81b2bb29840ba55b"
|
||||||
|
integrity sha512-ch+PI9rcp7FAddgF7ZyUfqptoSq1Ck0FadL/HHh6X1xazT+VwZdPy+Gtt2qjMCZhJfCkzjAGxvi1Hk4aFgr3vg==
|
||||||
dependencies:
|
dependencies:
|
||||||
datatables.net-bs4 "^1.10.15"
|
datatables.net-bs4 "^1.10.15"
|
||||||
datatables.net-select "1.2.7"
|
datatables.net-select "1.2.7"
|
||||||
@@ -133,6 +151,7 @@ datatables.net-select-bs4@^1.2.7:
|
|||||||
datatables.net-select@1.2.7, datatables.net-select@^1.2.7:
|
datatables.net-select@1.2.7, datatables.net-select@^1.2.7:
|
||||||
version "1.2.7"
|
version "1.2.7"
|
||||||
resolved "https://registry.yarnpkg.com/datatables.net-select/-/datatables.net-select-1.2.7.tgz#7d5badfca49c438f8b51df04483d8d77857e917c"
|
resolved "https://registry.yarnpkg.com/datatables.net-select/-/datatables.net-select-1.2.7.tgz#7d5badfca49c438f8b51df04483d8d77857e917c"
|
||||||
|
integrity sha512-C3XDi7wpruGjDXV36dc9hN/FrAX9GOFvBZ7+KfKJTBNkGFbbhdzHS91SMeGiwRXPYivAyxfPTcVVndVaO83uBQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
datatables.net "^1.10.15"
|
datatables.net "^1.10.15"
|
||||||
jquery ">=1.7"
|
jquery ">=1.7"
|
||||||
@@ -140,60 +159,73 @@ datatables.net-select@1.2.7, datatables.net-select@^1.2.7:
|
|||||||
datatables.net@1.10.16:
|
datatables.net@1.10.16:
|
||||||
version "1.10.16"
|
version "1.10.16"
|
||||||
resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-1.10.16.tgz#4b052d1082824261b68eed9d22741b711d3d2469"
|
resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-1.10.16.tgz#4b052d1082824261b68eed9d22741b711d3d2469"
|
||||||
|
integrity sha1-SwUtEIKCQmG2ju2dInQbcR09JGk=
|
||||||
dependencies:
|
dependencies:
|
||||||
jquery ">=1.7"
|
jquery ">=1.7"
|
||||||
|
|
||||||
datatables.net@1.10.19, datatables.net@^1.10.15, datatables.net@^1.10.19:
|
datatables.net@1.10.19, datatables.net@^1.10.15, datatables.net@^1.10.19:
|
||||||
version "1.10.19"
|
version "1.10.19"
|
||||||
resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-1.10.19.tgz#97a1ed41c85e62d61040603481b59790a172dd1f"
|
resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-1.10.19.tgz#97a1ed41c85e62d61040603481b59790a172dd1f"
|
||||||
|
integrity sha512-+ljXcI6Pj3PTGy5pesp3E5Dr3x3AV45EZe0o1r0gKENN2gafBKXodVnk2ypKwl2tTmivjxbkiqoWnipTefyBTA==
|
||||||
dependencies:
|
dependencies:
|
||||||
jquery ">=1.7"
|
jquery ">=1.7"
|
||||||
|
|
||||||
font-awesome@4.7.0:
|
font-awesome@4.7.0:
|
||||||
version "4.7.0"
|
version "4.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/font-awesome/-/font-awesome-4.7.0.tgz#8fa8cf0411a1a31afd07b06d2902bb9fc815a133"
|
resolved "https://registry.yarnpkg.com/font-awesome/-/font-awesome-4.7.0.tgz#8fa8cf0411a1a31afd07b06d2902bb9fc815a133"
|
||||||
|
integrity sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM=
|
||||||
|
|
||||||
jquery-serializejson@^2.8.1:
|
jquery-serializejson@^2.8.1:
|
||||||
version "2.8.1"
|
version "2.8.1"
|
||||||
resolved "https://registry.yarnpkg.com/jquery-serializejson/-/jquery-serializejson-2.8.1.tgz#fc40dd11e5d9a6fd2a3614fdcba89e4af794f0a8"
|
resolved "https://registry.yarnpkg.com/jquery-serializejson/-/jquery-serializejson-2.8.1.tgz#fc40dd11e5d9a6fd2a3614fdcba89e4af794f0a8"
|
||||||
|
integrity sha1-/EDdEeXZpv0qNhT9y6ieSveU8Kg=
|
||||||
|
|
||||||
jquery-ui-dist@^1.12.1:
|
jquery-ui-dist@^1.12.1:
|
||||||
version "1.12.1"
|
version "1.12.1"
|
||||||
resolved "https://registry.yarnpkg.com/jquery-ui-dist/-/jquery-ui-dist-1.12.1.tgz#5c0815d3cc6f90ff5faaf5b268a6e23b4ca904fa"
|
resolved "https://registry.yarnpkg.com/jquery-ui-dist/-/jquery-ui-dist-1.12.1.tgz#5c0815d3cc6f90ff5faaf5b268a6e23b4ca904fa"
|
||||||
|
integrity sha1-XAgV08xvkP9fqvWyaKbiO0ypBPo=
|
||||||
|
|
||||||
jquery.easing@^1.4.1:
|
jquery.easing@^1.4.1:
|
||||||
version "1.4.1"
|
version "1.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/jquery.easing/-/jquery.easing-1.4.1.tgz#47982c5836bd758fd48494923c4a101ef6e93e3b"
|
resolved "https://registry.yarnpkg.com/jquery.easing/-/jquery.easing-1.4.1.tgz#47982c5836bd758fd48494923c4a101ef6e93e3b"
|
||||||
|
integrity sha1-R5gsWDa9dY/UhJSSPEoQHvbpPjs=
|
||||||
|
|
||||||
jquery@1:
|
jquery@1:
|
||||||
version "1.12.4"
|
version "1.12.4"
|
||||||
resolved "https://registry.yarnpkg.com/jquery/-/jquery-1.12.4.tgz#01e1dfba290fe73deba77ceeacb0f9ba2fec9e0c"
|
resolved "https://registry.yarnpkg.com/jquery/-/jquery-1.12.4.tgz#01e1dfba290fe73deba77ceeacb0f9ba2fec9e0c"
|
||||||
|
integrity sha1-AeHfuikP5z3rp3zurLD5ui/sngw=
|
||||||
|
|
||||||
jquery@3.3.1, jquery@>=1.12.0, jquery@>=1.2.3, jquery@>=1.7, jquery@^3.0, jquery@^3.3.1:
|
jquery@3.3.1, jquery@>=1.12.0, jquery@>=1.2.3, jquery@>=1.7, jquery@^3.0, jquery@^3.3.1:
|
||||||
version "3.3.1"
|
version "3.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca"
|
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca"
|
||||||
|
integrity sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==
|
||||||
|
|
||||||
moment-timezone@^0.5.11:
|
moment-timezone@^0.5.11:
|
||||||
version "0.5.21"
|
version "0.5.21"
|
||||||
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.21.tgz#3cba247d84492174dbf71de2a9848fa13207b845"
|
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.21.tgz#3cba247d84492174dbf71de2a9848fa13207b845"
|
||||||
|
integrity sha512-j96bAh4otsgj3lKydm3K7kdtA3iKf2m6MY2iSYCzCm5a1zmHo1g+aK3068dDEeocLZQIS9kU8bsdQHLqEvgW0A==
|
||||||
dependencies:
|
dependencies:
|
||||||
moment ">= 2.9.0"
|
moment ">= 2.9.0"
|
||||||
|
|
||||||
"moment@>= 2.9.0", moment@^2.10.2, moment@^2.22.2:
|
"moment@>= 2.9.0", moment@^2.10.2, moment@^2.22.2:
|
||||||
version "2.22.2"
|
version "2.22.2"
|
||||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66"
|
resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66"
|
||||||
|
integrity sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=
|
||||||
|
|
||||||
moment@~2.18.0:
|
moment@~2.18.0:
|
||||||
version "2.18.1"
|
version "2.18.1"
|
||||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f"
|
resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f"
|
||||||
|
integrity sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8=
|
||||||
|
|
||||||
popper.js@^1.14.3:
|
popper.js@^1.14.3:
|
||||||
version "1.14.4"
|
version "1.14.4"
|
||||||
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.4.tgz#8eec1d8ff02a5a3a152dd43414a15c7b79fd69b6"
|
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.4.tgz#8eec1d8ff02a5a3a152dd43414a15c7b79fd69b6"
|
||||||
|
integrity sha1-juwdj/AqWjoVLdQ0FKFce3n9abY=
|
||||||
|
|
||||||
startbootstrap-sb-admin@^4.0.0:
|
startbootstrap-sb-admin@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/startbootstrap-sb-admin/-/startbootstrap-sb-admin-4.0.0.tgz#cf141a260d031b36bdc013c68200a1c1ea6c9881"
|
resolved "https://registry.yarnpkg.com/startbootstrap-sb-admin/-/startbootstrap-sb-admin-4.0.0.tgz#cf141a260d031b36bdc013c68200a1c1ea6c9881"
|
||||||
|
integrity sha512-qnIu5fcjAb288+MgeaOBnZ93eq4lXb3cpUgbqGUVG2afDRFgsIX0ii3BgbWHrQ7jYZRYADEKWe580F8uUpIAHg==
|
||||||
dependencies:
|
dependencies:
|
||||||
bootstrap "4.0.0"
|
bootstrap "4.0.0"
|
||||||
chart.js "2.7.1"
|
chart.js "2.7.1"
|
||||||
@@ -205,14 +237,17 @@ startbootstrap-sb-admin@^4.0.0:
|
|||||||
summernote@^0.8.10:
|
summernote@^0.8.10:
|
||||||
version "0.8.10"
|
version "0.8.10"
|
||||||
resolved "https://registry.yarnpkg.com/summernote/-/summernote-0.8.10.tgz#21a5d7f18a3b07500b58b60d5907417a54897520"
|
resolved "https://registry.yarnpkg.com/summernote/-/summernote-0.8.10.tgz#21a5d7f18a3b07500b58b60d5907417a54897520"
|
||||||
|
integrity sha512-1b4ESCiY9HW+12HYXCntjbThVgeYNaYKfKL7pC4Jqjo/WDS4G4mMtd2kPuCw56HxeRT67d+zlehopaE+M4o6aQ==
|
||||||
|
|
||||||
swagger-ui-dist@^3.17.3:
|
swagger-ui-dist@^3.17.3:
|
||||||
version "3.19.2"
|
version "3.19.4"
|
||||||
resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-3.19.2.tgz#3218f205e7cbc9f0c7c11fabbee07340173ae939"
|
resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-3.19.4.tgz#18053b1e7fa135c00dce0f2ebfaeb05d186cd5b5"
|
||||||
|
integrity sha512-YxC2mN53oXzF3hobm9cFhR14j9amNe2zUeKQa/tHckDJKItIxLQd+ksfeJgKw+pK04C2yppscOCFlIAvgR+jNQ==
|
||||||
|
|
||||||
tempusdominus-bootstrap-4@^5.0.1:
|
tempusdominus-bootstrap-4@^5.1.2:
|
||||||
version "5.1.1"
|
version "5.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/tempusdominus-bootstrap-4/-/tempusdominus-bootstrap-4-5.1.1.tgz#f1c765be4f17ffd86a56f2cb7fb7d4b19ea029c7"
|
resolved "https://registry.yarnpkg.com/tempusdominus-bootstrap-4/-/tempusdominus-bootstrap-4-5.1.2.tgz#3c9906ca6e5d563faa0b81b2fdc6aa79cad9c0be"
|
||||||
|
integrity sha512-ksD8qc4wOJeE19wvryXmEpRzMUSZu4wSOdG6zKSn8l4ccad16249KOX1j0CccyZpuuES/n4FLqLAUB+Dd1LTBA==
|
||||||
dependencies:
|
dependencies:
|
||||||
bootstrap ">=4.1.2"
|
bootstrap ">=4.1.2"
|
||||||
jquery "^3.0"
|
jquery "^3.0"
|
||||||
@@ -223,11 +258,13 @@ tempusdominus-bootstrap-4@^5.0.1:
|
|||||||
timeago@^1.6.3:
|
timeago@^1.6.3:
|
||||||
version "1.6.3"
|
version "1.6.3"
|
||||||
resolved "https://registry.yarnpkg.com/timeago/-/timeago-1.6.3.tgz#162a1adae99356297df59339837d09f1b0f36465"
|
resolved "https://registry.yarnpkg.com/timeago/-/timeago-1.6.3.tgz#162a1adae99356297df59339837d09f1b0f36465"
|
||||||
|
integrity sha512-x97d1X1KsNapWJTgCOOAy/59XagYu2WsDTAH/yvPsWi5bqtGbLPaVZBv3HZ3jTpakHR+JGGyrI9qC0yuvIAvnQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
jquery ">=1.2.3"
|
jquery ">=1.2.3"
|
||||||
|
|
||||||
toastr@^2.1.4:
|
toastr@^2.1.4:
|
||||||
version "2.1.4"
|
version "2.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/toastr/-/toastr-2.1.4.tgz#8b43be64fb9d0c414871446f2db8e8ca4e95f181"
|
resolved "https://registry.yarnpkg.com/toastr/-/toastr-2.1.4.tgz#8b43be64fb9d0c414871446f2db8e8ca4e95f181"
|
||||||
|
integrity sha1-i0O+ZPudDEFIcURvLbjoyk6V8YE=
|
||||||
dependencies:
|
dependencies:
|
||||||
jquery ">=1.12.0"
|
jquery ">=1.12.0"
|
||||||
|
Reference in New Issue
Block a user