Make it possible to copy products (closes #571)

This commit is contained in:
Bernd Bestel 2020-11-15 16:05:25 +01:00
parent 7d7f9bf07a
commit 9a7196b761
No known key found for this signature in database
GPG Key ID: 71BD34C0D4891300
5 changed files with 98 additions and 10 deletions

View File

@ -32,6 +32,7 @@ _- (Because the stock quantity unit is now the base for everything, it cannot be
- When creating a quantity unit conversion it's now possible to automatically create the inverse conversion (thanks @kriddles)
- On purchase there is now a warning shown, when the best before date of the purchased product is earlier than the next best before date in stock (enabled by default, can be disabled by a new stock setting (top right corner settings menu))
- The amount to be used for the "quick consume/open buttons" on the stock overview page can now be configured per product (new product option "Quick consume amount", defaults to 1)
- Products can now be duplicated (new button on the products list page, all fields will be preset from the copied product, except the name)
- Optimized/clarified what the total/unit price is on the purchase page (thanks @kriddles)
- On the purchase page the amount field is now displayed above/before the best before date for better `TAB` handling (thanks @kriddles)
- Changed that when `FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING` is disabled, products now get internally a best before of "never expires" (aka `2999-12-31`) instead of today (thanks @kriddles)

View File

@ -1942,3 +1942,9 @@ msgstr ""
msgid "This amount is used for the \"quick consume/open buttons\" on the stock overview page (related to quantity unit stock)"
msgstr ""
msgid "Copy this item"
msgstr ""
msgid "Are you sure to remove this barcode?"
msgstr ""

View File

@ -390,9 +390,6 @@ $(document).on('click', '.qu-conversion-delete-button', function(e)
$(document).on('click', '.barcode-delete-button', function(e)
{
var objectId = $(e.currentTarget).attr('data-barcode-id');
var productId = $(e.currentTarget).attr('data-product-id');
var barcode = $(e.currentTarget).attr('data-barcode');
var productBarcode = $(e.currentTarget).attr('data-product-barcode');
bootbox.confirm({
message: __t('Are you sure to remove this barcode?'),
@ -427,14 +424,15 @@ $(document).on('click', '.barcode-delete-button', function(e)
});
});
$('#qu_id_purchase').blur(function(e)
$('#qu_id_stock').change(function(e)
{
// Preset the stock quantity unit with the purchase quantity unit, if the stock quantity unit is unset.
var QuIdStock = $('#qu_id_stock');
var QuIdPurchase = $('#qu_id_purchase');
if (QuIdStock[0].selectedIndex === 0 && QuIdPurchase[0].selectedIndex !== 0)
// Preset QU purchase with stock QU if unset
var quIdStock = $('#qu_id_stock');
var quIdPurchase = $('#qu_id_purchase');
if (quIdPurchase[0].selectedIndex === 0 && quIdStock[0].selectedIndex !== 0)
{
QuIdStock[0].selectedIndex = QuIdPurchase[0].selectedIndex;
quIdPurchase[0].selectedIndex = quIdStock[0].selectedIndex;
Grocy.FrontendHelpers.ValidateForm('product-form');
}
});
@ -448,3 +446,65 @@ $(window).on("message", function(e)
window.location.reload();
}
});
if (Grocy.EditMode == "create" && GetUriParam("copy-of") != undefined)
{
Grocy.Api.Get('objects/products/' + GetUriParam("copy-of"),
function(sourceProduct)
{
if (sourceProduct.parent_product_id != null)
{
Grocy.Components.ProductPicker.SetId(sourceProduct.parent_product_id);
}
if (sourceProduct.description != null)
{
$("#description").summernote("pasteHTML", sourceProduct.description);
}
$("#location_id").val(sourceProduct.location_id);
if (sourceProduct.shopping_location_id != null)
{
Grocy.Components.ShoppingLocationPicker.SetId(sourceProduct.shopping_location_id);
}
$("#min_stock_amount").val(sourceProduct.min_stock_amount);
if (BoolVal(sourceProduct.cumulate_min_stock_amount_of_sub_products))
{
$("#cumulate_min_stock_amount_of_sub_products").prop("checked", true);
}
$("#default_best_before_days").val(sourceProduct.default_best_before_days);
$("#default_best_before_days_after_open").val(sourceProduct.default_best_before_days_after_open);
if (sourceProduct.product_group_id != null)
{
$("#product_group_id").val(sourceProduct.product_group_id);
}
$("#qu_id_stock").val(sourceProduct.qu_id_stock);
$("#qu_id_purchase").val(sourceProduct.qu_id_purchase);
$("#qu_factor_purchase_to_stock").val(sourceProduct.qu_factor_purchase_to_stock);
if (BoolVal(sourceProduct.allow_partial_units_in_stock))
{
$("#allow_partial_units_in_stock").prop("checked", true);
}
if (BoolVal(sourceProduct.enable_tare_weight_handling))
{
$("#enable_tare_weight_handling").prop("checked", true);
}
$("#tare_weight").val(sourceProduct.tare_weight);
if (BoolVal(sourceProduct.not_check_stock_fulfillment_for_recipes))
{
$("#not_check_stock_fulfillment_for_recipes").prop("checked", true);
}
if (sourceProduct.calories != null)
{
$("#calories").val(sourceProduct.calories);
}
$("#default_best_before_days_after_freezing").val(sourceProduct.default_best_before_days_after_freezing);
$("#default_best_before_days_after_thawing").val(sourceProduct.default_best_before_days_after_thawing);
$("#quick_consume_amount").val(sourceProduct.quick_consume_amount);
Grocy.FrontendHelpers.ValidateForm('product-form');
},
function(xhr)
{
console.error(xhr);
}
);
}

View File

@ -185,7 +185,17 @@
'invalidFeedback' => $__t('The amount cannot be lower than %s', '-1'),
'hint' => $__t('When this product was marked as opened, the best before date will be replaced by today + this amount of days (a value of 0 disables this)')
))
@else
<input type="hidden"
name="default_best_before_days_after_open"
id="default_best_before_days_after_open"
value="1">
@endif
@else
<input type="hidden"
name="default_best_before_days"
id="default_best_before_days"
value="1">
@endif
<div class="form-group">
@ -310,6 +320,12 @@
</label>
</div>
</div>
@else
<input type="hidden"
name="not_check_stock_fulfillment_for_recipes"
id="not_check_stock_fulfillment_for_recipes"
value="0">
@endif
@php if($mode == 'edit') { $value = $product->calories; } else { $value = 0; } @endphp
@include('components.numberpicker', array(
@ -323,7 +339,6 @@
'isRequired' => false,
'additionalCssClasses' => 'locale-number-input locale-number-quantity-amount'
))
@endif
@if(GROCY_FEATURE_FLAG_STOCK_PRODUCT_FREEZING)
@php if($mode == 'edit') { $value = $product->default_best_before_days_after_freezing; } else { $value = 0; } @endphp

View File

@ -118,6 +118,12 @@
title="{{ $__t('Edit this item') }}">
<i class="fas fa-edit"></i>
</a>
<a class="btn btn-primary btn-sm"
href="{{ $U('/product/new?copy-of=') }}{{ $product->id }}"
data-toggle="tooltip"
title="{{ $__t('Copy this item') }}">
<i class="fas fa-copy"></i>
</a>
<a class="btn btn-danger btn-sm product-delete-button @if($product->active == 0) disabled @endif"
href="#"
data-product-id="{{ $product->id }}"