mirror of
https://github.com/chenasraf/nextcloud-pantry.git
synced 2026-05-17 17:28:01 +00:00
refactor: shopping lists -> checklists
This commit is contained in:
@@ -7,19 +7,19 @@ declare(strict_types=1);
|
||||
|
||||
namespace OCA\Pantry\BackgroundJob;
|
||||
|
||||
use OCA\Pantry\Service\ShoppingListService;
|
||||
use OCA\Pantry\Service\ChecklistService;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\BackgroundJob\TimedJob;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Periodically reopens recurring shopping-list items whose next_due_at has
|
||||
* Periodically reopens recurring checklist items whose next_due_at has
|
||||
* passed, so they appear unchecked without waiting for a user to open the list.
|
||||
*/
|
||||
class ReopenRecurringItemsJob extends TimedJob {
|
||||
public function __construct(
|
||||
ITimeFactory $time,
|
||||
private ShoppingListService $lists,
|
||||
private ChecklistService $lists,
|
||||
private LoggerInterface $logger,
|
||||
) {
|
||||
parent::__construct($time);
|
||||
|
||||
@@ -13,7 +13,7 @@ use OCA\Pantry\ResponseDefinitions;
|
||||
use OCA\Pantry\Service\CategoryService;
|
||||
use OCA\Pantry\Service\HouseAuthService;
|
||||
use OCA\Pantry\Service\ImageService;
|
||||
use OCA\Pantry\Service\ShoppingListService;
|
||||
use OCA\Pantry\Service\ChecklistService;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\Attribute\ApiRoute;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
@@ -27,13 +27,13 @@ use OCP\IUserSession;
|
||||
* @psalm-import-type PantryListItem from ResponseDefinitions
|
||||
* @psalm-import-type PantrySuccess from ResponseDefinitions
|
||||
*/
|
||||
final class ShoppingListController extends OCSController {
|
||||
final class ChecklistController extends OCSController {
|
||||
use TranslatesDomainExceptions;
|
||||
|
||||
public function __construct(
|
||||
string $appName,
|
||||
IRequest $request,
|
||||
private ShoppingListService $lists,
|
||||
private ChecklistService $lists,
|
||||
private CategoryService $categories,
|
||||
private HouseAuthService $auth,
|
||||
private ImageService $images,
|
||||
@@ -43,7 +43,7 @@ final class ShoppingListController extends OCSController {
|
||||
}
|
||||
|
||||
/**
|
||||
* List all shopping lists in a house
|
||||
* List all checklists in a house
|
||||
*
|
||||
* @param int $houseId House id.
|
||||
* @param int<1, 500> $limit Maximum number of lists to return.
|
||||
@@ -66,7 +66,7 @@ final class ShoppingListController extends OCSController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a shopping list in a house
|
||||
* Create a checklist in a house
|
||||
*
|
||||
* @param int $houseId House id.
|
||||
* @param string $name List name.
|
||||
@@ -87,7 +87,7 @@ final class ShoppingListController extends OCSController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a shopping list
|
||||
* Get a checklist
|
||||
*
|
||||
* @param int $houseId House id.
|
||||
* @param int $listId List id.
|
||||
@@ -108,7 +108,7 @@ final class ShoppingListController extends OCSController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a shopping list
|
||||
* Update a checklist
|
||||
*
|
||||
* @param int $houseId House id.
|
||||
* @param int $listId List id.
|
||||
@@ -143,7 +143,7 @@ final class ShoppingListController extends OCSController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a shopping list
|
||||
* Delete a checklist
|
||||
*
|
||||
* @param int $houseId House id.
|
||||
* @param int $listId List id.
|
||||
@@ -165,7 +165,7 @@ final class ShoppingListController extends OCSController {
|
||||
}
|
||||
|
||||
/**
|
||||
* List items in a shopping list
|
||||
* List items in a checklist
|
||||
*
|
||||
* Auto-reopens recurring items whose next occurrence has arrived.
|
||||
*
|
||||
@@ -23,7 +23,7 @@ use OCP\AppFramework\Db\Entity;
|
||||
* @method int getUpdatedAt()
|
||||
* @method void setUpdatedAt(int $updatedAt)
|
||||
*/
|
||||
class ShoppingList extends Entity implements \JsonSerializable {
|
||||
class Checklist extends Entity implements \JsonSerializable {
|
||||
protected int $houseId = 0;
|
||||
protected string $name = '';
|
||||
protected ?string $description = null;
|
||||
@@ -39,7 +39,7 @@ use OCP\AppFramework\Db\Entity;
|
||||
* @method int getUpdatedAt()
|
||||
* @method void setUpdatedAt(int $updatedAt)
|
||||
*/
|
||||
class ShoppingListItem extends Entity implements \JsonSerializable {
|
||||
class ChecklistItem extends Entity implements \JsonSerializable {
|
||||
protected int $listId = 0;
|
||||
protected string $name = '';
|
||||
protected ?int $categoryId = null;
|
||||
@@ -14,15 +14,15 @@ use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IDBConnection;
|
||||
|
||||
/**
|
||||
* @template-extends QBMapper<ShoppingListItem>
|
||||
* @template-extends QBMapper<ChecklistItem>
|
||||
*/
|
||||
class ShoppingListItemMapper extends QBMapper {
|
||||
class ChecklistItemMapper extends QBMapper {
|
||||
public function __construct(IDBConnection $db) {
|
||||
parent::__construct($db, Application::tableName('list_items'), ShoppingListItem::class);
|
||||
parent::__construct($db, Application::tableName('list_items'), ChecklistItem::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ShoppingListItem[]
|
||||
* @return ChecklistItem[]
|
||||
*/
|
||||
public function findByList(int $listId): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
@@ -38,7 +38,7 @@ class ShoppingListItemMapper extends QBMapper {
|
||||
/**
|
||||
* @throws DoesNotExistException
|
||||
*/
|
||||
public function findById(int $id): ShoppingListItem {
|
||||
public function findById(int $id): ChecklistItem {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
@@ -50,7 +50,7 @@ class ShoppingListItemMapper extends QBMapper {
|
||||
/**
|
||||
* Find all bought items whose next_due_at has passed.
|
||||
*
|
||||
* @return ShoppingListItem[]
|
||||
* @return ChecklistItem[]
|
||||
*/
|
||||
public function findDueRecurring(int $now): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
@@ -14,15 +14,15 @@ use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IDBConnection;
|
||||
|
||||
/**
|
||||
* @template-extends QBMapper<ShoppingList>
|
||||
* @template-extends QBMapper<Checklist>
|
||||
*/
|
||||
class ShoppingListMapper extends QBMapper {
|
||||
class ChecklistMapper extends QBMapper {
|
||||
public function __construct(IDBConnection $db) {
|
||||
parent::__construct($db, Application::tableName('lists'), ShoppingList::class);
|
||||
parent::__construct($db, Application::tableName('lists'), Checklist::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ShoppingList[]
|
||||
* @return Checklist[]
|
||||
*/
|
||||
public function findByHouse(int $houseId): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
@@ -38,7 +38,7 @@ class ShoppingListMapper extends QBMapper {
|
||||
/**
|
||||
* @throws DoesNotExistException
|
||||
*/
|
||||
public function findById(int $id): ShoppingList {
|
||||
public function findById(int $id): Checklist {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
@@ -15,7 +15,7 @@ use OCP\Migration\IOutput;
|
||||
use OCP\Migration\SimpleMigrationStep;
|
||||
|
||||
/**
|
||||
* Initial schema for Pantry: houses, members, shopping lists, list items.
|
||||
* Initial schema for Pantry: houses, members, checklists, list items.
|
||||
*/
|
||||
class Version1Date20260405000000 extends SimpleMigrationStep {
|
||||
/**
|
||||
|
||||
@@ -7,17 +7,17 @@ declare(strict_types=1);
|
||||
|
||||
namespace OCA\Pantry\Service;
|
||||
|
||||
use OCA\Pantry\Db\ShoppingList;
|
||||
use OCA\Pantry\Db\ShoppingListItem;
|
||||
use OCA\Pantry\Db\ShoppingListItemMapper;
|
||||
use OCA\Pantry\Db\ShoppingListMapper;
|
||||
use OCA\Pantry\Db\Checklist;
|
||||
use OCA\Pantry\Db\ChecklistItem;
|
||||
use OCA\Pantry\Db\ChecklistItemMapper;
|
||||
use OCA\Pantry\Db\ChecklistMapper;
|
||||
use OCA\Pantry\Exception\NotFoundException;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
|
||||
class ShoppingListService {
|
||||
class ChecklistService {
|
||||
public function __construct(
|
||||
private ShoppingListMapper $listMapper,
|
||||
private ShoppingListItemMapper $itemMapper,
|
||||
private ChecklistMapper $listMapper,
|
||||
private ChecklistItemMapper $itemMapper,
|
||||
private RecurrenceService $recurrence,
|
||||
) {
|
||||
}
|
||||
@@ -25,13 +25,13 @@ class ShoppingListService {
|
||||
// ----- Lists -----
|
||||
|
||||
/**
|
||||
* @return ShoppingList[]
|
||||
* @return Checklist[]
|
||||
*/
|
||||
public function listForHouse(int $houseId): array {
|
||||
return $this->listMapper->findByHouse($houseId);
|
||||
}
|
||||
|
||||
public function getList(int $listId): ShoppingList {
|
||||
public function getList(int $listId): Checklist {
|
||||
try {
|
||||
return $this->listMapper->findById($listId);
|
||||
} catch (DoesNotExistException) {
|
||||
@@ -39,25 +39,25 @@ class ShoppingListService {
|
||||
}
|
||||
}
|
||||
|
||||
public function createList(int $houseId, string $name, ?string $description): ShoppingList {
|
||||
public function createList(int $houseId, string $name, ?string $description): Checklist {
|
||||
$name = trim($name);
|
||||
if ($name === '') {
|
||||
throw new \InvalidArgumentException('List name cannot be empty');
|
||||
}
|
||||
$now = time();
|
||||
$list = new ShoppingList();
|
||||
$list = new Checklist();
|
||||
$list->setHouseId($houseId);
|
||||
$list->setName($name);
|
||||
$list->setDescription($description !== null && $description !== '' ? $description : null);
|
||||
$list->setSortOrder(0);
|
||||
$list->setCreatedAt($now);
|
||||
$list->setUpdatedAt($now);
|
||||
/** @var ShoppingList $saved */
|
||||
/** @var Checklist $saved */
|
||||
$saved = $this->listMapper->insert($list);
|
||||
return $saved;
|
||||
}
|
||||
|
||||
public function updateList(int $listId, array $patch): ShoppingList {
|
||||
public function updateList(int $listId, array $patch): Checklist {
|
||||
$list = $this->getList($listId);
|
||||
if (isset($patch['name'])) {
|
||||
$name = trim((string)$patch['name']);
|
||||
@@ -89,7 +89,7 @@ class ShoppingListService {
|
||||
/**
|
||||
* List items for a list, auto-unchecking any recurring items whose next_due_at has passed.
|
||||
*
|
||||
* @return ShoppingListItem[]
|
||||
* @return ChecklistItem[]
|
||||
*/
|
||||
public function listItems(int $listId, ?int $now = null): array {
|
||||
// Eagerly reopen any due recurring items in this list before returning.
|
||||
@@ -97,7 +97,7 @@ class ShoppingListService {
|
||||
return $this->itemMapper->findByList($listId);
|
||||
}
|
||||
|
||||
public function getItem(int $itemId): ShoppingListItem {
|
||||
public function getItem(int $itemId): ChecklistItem {
|
||||
try {
|
||||
return $this->itemMapper->findById($itemId);
|
||||
} catch (DoesNotExistException) {
|
||||
@@ -105,7 +105,7 @@ class ShoppingListService {
|
||||
}
|
||||
}
|
||||
|
||||
public function addItem(int $listId, array $data): ShoppingListItem {
|
||||
public function addItem(int $listId, array $data): ChecklistItem {
|
||||
// Ensure the list exists.
|
||||
$this->getList($listId);
|
||||
|
||||
@@ -122,7 +122,7 @@ class ShoppingListService {
|
||||
}
|
||||
|
||||
$now = time();
|
||||
$item = new ShoppingListItem();
|
||||
$item = new ChecklistItem();
|
||||
$item->setListId($listId);
|
||||
$item->setName($name);
|
||||
$item->setCategoryId($this->intOrNull($data['categoryId'] ?? null));
|
||||
@@ -137,12 +137,12 @@ class ShoppingListService {
|
||||
$item->setSortOrder(isset($data['sortOrder']) ? (int)$data['sortOrder'] : 0);
|
||||
$item->setCreatedAt($now);
|
||||
$item->setUpdatedAt($now);
|
||||
/** @var ShoppingListItem $saved */
|
||||
/** @var ChecklistItem $saved */
|
||||
$saved = $this->itemMapper->insert($item);
|
||||
return $saved;
|
||||
}
|
||||
|
||||
public function updateItem(int $itemId, array $patch): ShoppingListItem {
|
||||
public function updateItem(int $itemId, array $patch): ChecklistItem {
|
||||
$item = $this->getItem($itemId);
|
||||
|
||||
if (isset($patch['name'])) {
|
||||
@@ -192,7 +192,7 @@ class ShoppingListService {
|
||||
return $item;
|
||||
}
|
||||
|
||||
public function toggleItem(int $itemId, string $uid, ?int $now = null): ShoppingListItem {
|
||||
public function toggleItem(int $itemId, string $uid, ?int $now = null): ChecklistItem {
|
||||
$item = $this->getItem($itemId);
|
||||
$now ??= time();
|
||||
|
||||
@@ -221,7 +221,7 @@ class ShoppingListService {
|
||||
* - "fixed schedule" mode: the schedule is anchored at the item's creation time; next
|
||||
* occurrence is the first one strictly after now on that anchored series.
|
||||
*/
|
||||
private function computeNextDueAt(ShoppingListItem $item, int $now): ?\DateTimeImmutable {
|
||||
private function computeNextDueAt(ChecklistItem $item, int $now): ?\DateTimeImmutable {
|
||||
$rrule = $item->getRrule();
|
||||
if ($rrule === null) {
|
||||
return null;
|
||||
@@ -8,6 +8,8 @@ declare(strict_types=1);
|
||||
namespace OCA\Pantry\Service;
|
||||
|
||||
use OCA\Pantry\Db\CategoryMapper;
|
||||
use OCA\Pantry\Db\ChecklistItemMapper;
|
||||
use OCA\Pantry\Db\ChecklistMapper;
|
||||
use OCA\Pantry\Db\House;
|
||||
use OCA\Pantry\Db\HouseMapper;
|
||||
use OCA\Pantry\Db\HouseMember;
|
||||
@@ -15,8 +17,6 @@ use OCA\Pantry\Db\HouseMemberMapper;
|
||||
use OCA\Pantry\Db\NoteMapper;
|
||||
use OCA\Pantry\Db\PhotoFolderMapper;
|
||||
use OCA\Pantry\Db\PhotoMapper;
|
||||
use OCA\Pantry\Db\ShoppingListItemMapper;
|
||||
use OCA\Pantry\Db\ShoppingListMapper;
|
||||
use OCA\Pantry\Exception\ForbiddenException;
|
||||
use OCA\Pantry\Exception\NotFoundException;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
@@ -27,8 +27,8 @@ class HouseService {
|
||||
public function __construct(
|
||||
private HouseMapper $houseMapper,
|
||||
private HouseMemberMapper $memberMapper,
|
||||
private ShoppingListMapper $listMapper,
|
||||
private ShoppingListItemMapper $itemMapper,
|
||||
private ChecklistMapper $listMapper,
|
||||
private ChecklistItemMapper $itemMapper,
|
||||
private CategoryMapper $categoryMapper,
|
||||
private PhotoMapper $photoMapper,
|
||||
private PhotoFolderMapper $photoFolderMapper,
|
||||
|
||||
@@ -12,7 +12,7 @@ use OCP\Files\IRootFolder;
|
||||
use OCP\Files\NotPermittedException;
|
||||
|
||||
class ImageService {
|
||||
public const SHOPPING_ITEMS_SUBDIR = 'Shopping list items';
|
||||
public const CHECKLIST_ITEMS_SUBDIR = 'Checklist items';
|
||||
public const PHOTO_WALL_SUBDIR = 'Photo wall';
|
||||
|
||||
public function __construct(
|
||||
@@ -29,7 +29,7 @@ class ImageService {
|
||||
if ($data === '') {
|
||||
throw new \InvalidArgumentException('Empty file');
|
||||
}
|
||||
$folder = $this->resolveShoppingItemsFolder($uid, $houseId);
|
||||
$folder = $this->resolveChecklistItemsFolder($uid, $houseId);
|
||||
$filename = $this->uniqueName($folder, $originalName);
|
||||
try {
|
||||
$file = $folder->newFile($filename, $data);
|
||||
@@ -62,9 +62,9 @@ class ImageService {
|
||||
return $this->getOrCreateSubFolder($base, self::PHOTO_WALL_SUBDIR);
|
||||
}
|
||||
|
||||
private function resolveShoppingItemsFolder(string $uid, int $houseId): Folder {
|
||||
private function resolveChecklistItemsFolder(string $uid, int $houseId): Folder {
|
||||
$base = $this->resolveBaseFolder($uid, $houseId);
|
||||
return $this->getOrCreateSubFolder($base, self::SHOPPING_ITEMS_SUBDIR);
|
||||
return $this->getOrCreateSubFolder($base, self::CHECKLIST_ITEMS_SUBDIR);
|
||||
}
|
||||
|
||||
private function resolveBaseFolder(string $uid, int $houseId): Folder {
|
||||
|
||||
Reference in New Issue
Block a user