Skip to content

Commit

Permalink
Merge pull request #306 from karlomikus/develop
Browse files Browse the repository at this point in the history
Add prices/price categories
  • Loading branch information
karlomikus authored Aug 2, 2024
2 parents cf53685 + bd0e449 commit aecdbf1
Show file tree
Hide file tree
Showing 62 changed files with 1,885 additions and 858 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
# v3.18.0
## New
- Added price categories
- Categorize prices by currency and name
- Added ingredient prices
- Add price per unit
- Assign price categories
- Added `json+ld` cocktail share type

## Changes
- Added `intl` PHP extension to docker images

# v3.17.1
## Fixes
- Fix glass volume not nullable #301
Expand Down
8 changes: 4 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM php:8.2-fpm as php-base
FROM php:8.2-fpm AS php-base

ARG PGID=1000
ENV PGID=${PGID}
Expand All @@ -16,7 +16,7 @@ RUN apt update \
bash \
cron \
&& chmod +x /usr/local/bin/install-php-extensions \
&& install-php-extensions imagick opcache redis zip pcntl bcmath \
&& install-php-extensions imagick opcache redis zip pcntl bcmath intl \
&& echo "access.log = /dev/null" >> /usr/local/etc/php-fpm.d/www.conf \
&& apt-get autoremove -y \
&& apt-get clean \
Expand All @@ -32,7 +32,7 @@ WORKDIR /var/www/cocktails

CMD ["php-fpm"]

FROM php-base as dist
FROM php-base AS dist

ARG BAR_ASSISTANT_VERSION
ENV BAR_ASSISTANT_VERSION=${BAR_ASSISTANT_VERSION:-develop}
Expand Down Expand Up @@ -73,7 +73,7 @@ VOLUME ["/var/www/cocktails/storage/bar-assistant"]

ENTRYPOINT ["entrypoint"]

FROM php-base as localdev
FROM php-base AS localdev

RUN useradd -G www-data,root -u $PUID -d /home/developer developer
RUN mkdir -p /home/developer/.composer && \
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
</p>

<p align="center">
<a href="https://hub.docker.com/r/barassistant/server"><img src="https://img.shields.io/docker/v/barassistant/server?style=for-the-badge&sort=semver" alt="Docker image"></a>
<img src="https://img.shields.io/docker/v/barassistant/server?style=for-the-badge&sort=semver" alt="Docker image">
<img src="https://img.shields.io/github/license/karlomikus/bar-assistant?style=for-the-badge" alt="Docker image">
<img src="https://img.shields.io/github/actions/workflow/status/karlomikus/bar-assistant/php.yml?branch=master&style=for-the-badge&label=Tests" alt="Tests">
<img src="https://img.shields.io/docker/pulls/barassistant/server?style=for-the-badge" alt="Pulls">
<a href="https://hub.docker.com/r/barassistant/server"><img src="https://img.shields.io/docker/pulls/barassistant/server?style=for-the-badge" alt="Pulls"></a>
</p>

## 🍸 Bar Assistant

Bar Assistant is a self hosted application for managing your home bar. It allows you to search and filter cocktails, add ingredients and create custom cocktail recipes.
Bar Assistant is all-in-one solution for managing your home bar. Compared to other recipe management software that usually tries to be more for general use, Bar Assistant is made specifically for managing cocktail recipes. This means that there are a lot of cocktail-oriented features, like ingredient substitutes, first-class ingredients, ABV calculations, unit switching and more.

This repository only contains the API server, if you are looking for easy to use web client, take a look at [Salt Rim](https://github.com/karlomikus/vue-salt-rim).

Expand Down Expand Up @@ -46,9 +46,9 @@ This repository only contains the API server, if you are looking for easy to use
- Manage custom API personal access tokens with custom permissions set by users
- Detailed statistics about recipes and user tastes

## Cloud
## Managed instance

Visit [barassistant.app](https://barassistant.app/) for more information about our cloud offering.
Bar Assistant will always be open-source and MIT-licensed, but if you want to support the project or don't want to self-host, you can try officialy managed instance. Visit [barassistant.app](https://barassistant.app/) for more information about our cloud offering.

![Cloud offering screenshot](/resources/art/art1.png)

Expand Down
6 changes: 3 additions & 3 deletions UPCOMING.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Breaking
- Remove collections share
- Encode images into export file
- Compress / compare
- Bump php to 8.3
- Change export format
- Bump php to 8.3
- Use unprivileged image
8 changes: 8 additions & 0 deletions app/DTO/Ingredient/Ingredient.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
{
/**
* @param array<int> $images
* @param array<Price> $prices
*/
public function __construct(
public int $barId,
Expand All @@ -23,11 +24,17 @@ public function __construct(
public ?int $parentIngredientId = null,
public array $images = [],
public array $complexIngredientParts = [],
public array $prices = [],
) {
}

public static function fromIlluminateRequest(Request $request, int $barId): self
{
$prices = [];
foreach ($request->post('prices', []) as $price) {
$prices[] = Price::fromArray($price);
}

return new self(
$barId,
$request->post('name'),
Expand All @@ -40,6 +47,7 @@ public static function fromIlluminateRequest(Request $request, int $barId): self
$request->post('parent_ingredient_id') ? (int) $request->post('parent_ingredient_id') : null,
$request->post('images', []),
$request->post('complex_ingredient_part_ids', []),
$prices,
);
}
}
39 changes: 39 additions & 0 deletions app/DTO/Ingredient/Price.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace Kami\Cocktail\DTO\Ingredient;

use Brick\Money\Money;
use Brick\Math\RoundingMode;
use Kami\Cocktail\Models\PriceCategory;

readonly class Price
{
public function __construct(
public int $priceCategoryId,
public int $price,
public float $amount,
public string $units,
public ?string $description = null,
) {
}

public static function fromArray(array $source): self
{
$category = PriceCategory::findOrFail((int) $source['price_category_id']);
$price = Money::of(
$source['price'],
$category->getCurrency()->value,
roundingMode: RoundingMode::UP
)->getMinorAmount()->toInt();

return new self(
(int) $category->id,
$price,
(float) $source['amount'],
$source['units'],
$source['description'] ?? null,
);
}
}
4 changes: 2 additions & 2 deletions app/External/Cocktail.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ public static function fromModel(CocktailModel $model): self
$model->getExternalId(),
$model->name,
$model->instructions,
$model->created_at->toDateTimeString(),
$model->updated_at?->toDateTimeString(),
$model->created_at->toIso8601String(),
$model->updated_at?->toIso8601String(),
$model->description,
$model->source,
$model->garnish,
Expand Down
26 changes: 11 additions & 15 deletions app/External/Export/Recipes.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,7 @@ private function dumpCocktails(int $barId, ZipArchive &$zip, ExportTypeEnum $typ
// Overwrite images with local filepaths
$data['images'] = $externalImages;

if ($type === ExportTypeEnum::YAML) {
$cocktailExportData = Yaml::dump($data, 8, 4, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK);
} else {
$cocktailExportData = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
}
$cocktailExportData = $this->prepareDataOutput($type, $data);

$zip->addFromString('cocktails/' . $data['_id'] . '.' . $type->value, $cocktailExportData);
}
Expand Down Expand Up @@ -119,11 +115,7 @@ private function dumpIngredients(int $barId, ZipArchive &$zip, ExportTypeEnum $t
// Overwrite images with local filepaths
$data['images'] = $externalImages;

if ($type === ExportTypeEnum::YAML) {
$ingredientExportData = Yaml::dump($data, 8, 4, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK);
} else {
$ingredientExportData = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
}
$ingredientExportData = $this->prepareDataOutput($type, $data);

$zip->addFromString('ingredients/' . $data['_id'] . '.' . $type->value, $ingredientExportData);
}
Expand All @@ -139,13 +131,17 @@ private function dumpBaseData(int $barId, ZipArchive &$zip, ExportTypeEnum $type
];

foreach ($baseDataFiles as $file => $data) {
if ($type === ExportTypeEnum::YAML) {
$exportData = Yaml::dump($data, 8, 4, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK | Yaml::DUMP_OBJECT_AS_MAP);
} else {
$exportData = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
}
$exportData = $this->prepareDataOutput($type, $data);

$zip->addFromString($file . '.' . $type->value, $exportData);
}
}

private function prepareDataOutput(ExportTypeEnum $type, array $data): string
{
return match ($type) {
ExportTypeEnum::JSON => json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
ExportTypeEnum::YAML => Yaml::dump($data, 8, 4, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK),
};
}
}
2 changes: 1 addition & 1 deletion app/External/Image.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public static function fromModel(ImageModel $model): self

public static function fromArray(array $sourceArray): self
{
$source = $sourceArray['source'] ?? $sourceArray['file_name'] ?? $sourceArray['url'] ?? null;
$source = $sourceArray['uri'] ?? $sourceArray['source'] ?? $sourceArray['file_name'] ?? $sourceArray['url'] ?? null;

return new self(
$source,
Expand Down
4 changes: 2 additions & 2 deletions app/External/IngredientWithImages.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ public static function fromModel(IngredientModel $model): self
$model->origin,
$model->color,
$model->category?->name ?? null,
$model->created_at->toDateTimeString(),
$model->updated_at?->toDateTimeString(),
$model->created_at->toIso8601String(),
$model->updated_at?->toIso8601String(),
$images,
$ingredientParts,
);
Expand Down
10 changes: 7 additions & 3 deletions app/Http/Controllers/CocktailController.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use Illuminate\Support\Facades\Validator;
use Kami\RecipeUtils\UnitConverter\Units;
use Kami\Cocktail\Services\CocktailService;
use Kami\Cocktail\Rules\IngredientBelongsToBar;
use Kami\Cocktail\Rules\ResourceBelongsToBar;
use Illuminate\Http\Resources\Json\JsonResource;
use Kami\Cocktail\Http\Requests\CocktailRequest;
use Kami\Cocktail\Repository\CocktailRepository;
Expand Down Expand Up @@ -65,7 +65,7 @@ public function show(string $idOrSlug, Request $request): JsonResource
public function store(CocktailService $cocktailService, CocktailRequest $request): JsonResponse
{
Validator::make($request->post('ingredients', []), [
'*.ingredient_id' => [new IngredientBelongsToBar(bar()->id)],
'*.ingredient_id' => [new ResourceBelongsToBar(bar()->id, 'ingredients')],
])->validate();

if ($request->user()->cannot('create', Cocktail::class)) {
Expand Down Expand Up @@ -95,7 +95,7 @@ public function update(CocktailService $cocktailService, CocktailRequest $reques
$cocktail = Cocktail::findOrFail($id);

Validator::make($request->post('ingredients', []), [
'*.ingredient_id' => [new IngredientBelongsToBar($cocktail->bar_id)],
'*.ingredient_id' => [new ResourceBelongsToBar($cocktail->bar_id, 'ingredients')],
])->validate();

if ($request->user()->cannot('edit', $cocktail)) {
Expand Down Expand Up @@ -195,6 +195,10 @@ public function share(Request $request, string $idOrSlug): Response
return new Response(json_encode($data, JSON_UNESCAPED_UNICODE), 200, ['Content-Type' => 'application/json']);
}

if ($type === 'json+ld') {
return new Response(json_encode($cocktail->asJsonLDSchema(), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), 200, ['Content-Type' => 'application/json']);
}

if ($type === 'yaml' || $type === 'yml') {
return new Response(Yaml::dump($data, 4, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK), 200, ['Content-Type' => 'application/yaml']);
}
Expand Down
10 changes: 6 additions & 4 deletions app/Http/Controllers/IngredientController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use Kami\Cocktail\Models\Cocktail;
use Kami\Cocktail\Models\Ingredient;
use Illuminate\Support\Facades\Validator;
use Kami\Cocktail\Rules\IngredientBelongsToBar;
use Kami\Cocktail\Rules\ResourceBelongsToBar;
use Kami\Cocktail\Services\IngredientService;
use Illuminate\Http\Resources\Json\JsonResource;
use Kami\Cocktail\Repository\CocktailRepository;
Expand All @@ -36,7 +36,7 @@ public function index(IngredientRepository $ingredientQuery, Request $request):

public function show(Request $request, string $id): JsonResource
{
$ingredient = Ingredient::with('cocktails', 'images', 'varieties', 'parentIngredient', 'createdUser', 'updatedUser', 'ingredientParts.ingredient')
$ingredient = Ingredient::with('cocktails', 'images', 'varieties', 'parentIngredient', 'createdUser', 'updatedUser', 'ingredientParts.ingredient', 'prices.priceCategory')
->withCount('cocktails')
->where('id', $id)
->orWhere('slug', $id)
Expand All @@ -52,7 +52,8 @@ public function show(Request $request, string $id): JsonResource
public function store(IngredientService $ingredientService, IngredientRequest $request): JsonResponse
{
Validator::make($request->all(), [
'complex_ingredient_part_ids' => [new IngredientBelongsToBar(bar()->id)],
'complex_ingredient_part_ids' => [new ResourceBelongsToBar(bar()->id, 'ingredients')],
'prices.*.price_category_id' => [new ResourceBelongsToBar(bar()->id, 'price_categories')],
])->validate();

if ($request->user()->cannot('create', Ingredient::class)) {
Expand All @@ -74,7 +75,8 @@ public function update(IngredientService $ingredientService, IngredientRequest $
$ingredient = Ingredient::findOrFail($id);

Validator::make($request->all(), [
'complex_ingredient_part_ids' => [new IngredientBelongsToBar($ingredient->bar_id)],
'complex_ingredient_part_ids' => [new ResourceBelongsToBar($ingredient->bar_id, 'ingredients')],
'prices.*.price_category_id' => [new ResourceBelongsToBar($ingredient->bar_id, 'price_categories')],
])->validate();

if ($request->user()->cannot('edit', $ingredient)) {
Expand Down
Loading

0 comments on commit aecdbf1

Please sign in to comment.