mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Merge pull request #8258 from turbo124/v5-develop
Attach recurring invoice docs
This commit is contained in:
commit
eff0945c08
@ -10,9 +10,7 @@
|
||||
|
||||
## [Hosted](https://www.invoiceninja.com) | [Self-Hosted](https://www.invoiceninja.org)
|
||||
|
||||
Join us on [Slack](http://slack.invoiceninja.com), [Discord](https://discord.com/channels/1071654583870435439/1071654584390537279) [Discourse](https://forum.invoiceninja.com) -
|
||||
or [StackOverflow](https://stackoverflow.com/tags/invoice-ninja/) if you like,
|
||||
just make sure to add the `invoice-ninja` tag to your question.
|
||||
Join us on [Slack](http://slack.invoiceninja.com), [Discord](https://discord.gg/ZwEdtfCwXA), [Support Forum](https://forum.invoiceninja.com)
|
||||
|
||||
## Introduction
|
||||
|
||||
@ -27,13 +25,13 @@ We offer a $30 per year white-label license to remove the Invoice Ninja branding
|
||||
* [API Documentation](https://app.swaggerhub.com/apis/invoiceninja/invoiceninja)
|
||||
* [APP Documentation](https://invoiceninja.github.io/)
|
||||
* [Support Forum](https://forum.invoiceninja.com)
|
||||
* [StackOverflow](https://stackoverflow.com/tags/invoice-ninja/)
|
||||
|
||||
## Setup
|
||||
|
||||
### Mobile Apps
|
||||
* [iPhone](https://apps.apple.com/app/id1503970375?platform=iphone)
|
||||
* [Android](https://play.google.com/store/apps/details?id=com.invoiceninja.app)
|
||||
* [F-Droid](https://f-droid.org/en/packages/com.invoiceninja.app)
|
||||
|
||||
### Desktop Apps
|
||||
* [macOS](https://apps.apple.com/app/id1503970375?platform=mac)
|
||||
@ -55,7 +53,7 @@ We offer a $30 per year white-label license to remove the Invoice Ninja branding
|
||||
git clone https://github.com/invoiceninja/invoiceninja.git
|
||||
git checkout v5-stable
|
||||
cp .env.example .env
|
||||
composer update
|
||||
composer i -o --no-dev
|
||||
php artisan key:generate
|
||||
```
|
||||
|
||||
|
@ -1 +1 @@
|
||||
5.5.68
|
||||
5.5.69
|
@ -1031,6 +1031,11 @@ class BaseController extends Controller
|
||||
public function flutterRoute()
|
||||
{
|
||||
if ((bool) $this->checkAppSetup() !== false && $account = Account::first()) {
|
||||
|
||||
//always redirect invoicing.co to invoicing.co
|
||||
if(Ninja::isHosted() && (request()->getSchemeAndHttpHost() != 'https://invoicing.co'))
|
||||
return redirect()->secure('https://invoicing.co');
|
||||
|
||||
if (config('ninja.require_https') && ! request()->isSecure()) {
|
||||
return redirect()->secure(request()->getRequestUri());
|
||||
}
|
||||
|
@ -322,6 +322,7 @@ class BillingPortalPurchasev2 extends Component
|
||||
'total' => $total,
|
||||
'qty' => $qty,
|
||||
'is_recurring' => true,
|
||||
'product_image' => $p->product_image,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ class GenericReportRequest extends Request
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if (! array_key_exists('date_range', $input)) {
|
||||
if (! array_key_exists('date_range', $input) || $input['date_range'] == '') {
|
||||
$input['date_range'] = 'all';
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ class ProductSalesReportRequest extends Request
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if (! array_key_exists('date_range', $input)) {
|
||||
if (! array_key_exists('date_range', $input) || $input['date_range'] == '') {
|
||||
$input['date_range'] = 'all';
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ class ProfitLossRequest extends Request
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if (! array_key_exists('date_range', $input)) {
|
||||
if (! array_key_exists('date_range', $input) || $input['date_range'] == '') {
|
||||
$input['date_range'] = 'all';
|
||||
}
|
||||
|
||||
|
@ -138,6 +138,17 @@ class InvoiceEmailEngine extends BaseEmailEngine
|
||||
if ($this->client->getSetting('document_email_attachment') !== false && $this->invoice->company->account->hasFeature(Account::FEATURE_DOCUMENTS)) {
|
||||
|
||||
|
||||
if($this->invoice->recurring_invoice()->exists())
|
||||
{
|
||||
foreach ($this->invoice->recurring_invoice->documents as $document) {
|
||||
|
||||
if($document->size > $this->max_attachment_size)
|
||||
$this->setAttachmentLinks(["<a class='doc_links' href='" . URL::signedRoute('documents.public_download', ['document_hash' => $document->hash]) ."'>". $document->name ."</a>"]);
|
||||
else
|
||||
$this->setAttachments([['file' => base64_encode($document->getFile()), 'path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
|
||||
}
|
||||
}
|
||||
|
||||
// Storage::url
|
||||
foreach ($this->invoice->documents as $document) {
|
||||
|
||||
|
@ -163,9 +163,9 @@ class BankTransactionRule extends BaseModel
|
||||
return $this->belongsTo(User::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function expense_cateogry()
|
||||
public function expense_category()
|
||||
{
|
||||
return $this->belongsTo(ExpenseCategory::class)->withTrashed();
|
||||
return $this->belongsTo(ExpenseCategory::class, 'category_id', 'id')->withTrashed();
|
||||
}
|
||||
|
||||
}
|
@ -39,6 +39,8 @@ class Product extends BaseModel
|
||||
'in_stock_quantity',
|
||||
'stock_notification_threshold',
|
||||
'stock_notification',
|
||||
'max_quantity',
|
||||
'product_image',
|
||||
];
|
||||
|
||||
protected $touches = [];
|
||||
|
@ -82,7 +82,7 @@ class ClientContactObserver
|
||||
|
||||
CreditInvitation::withTrashed()->where('client_contact_id', $client_contact_id)->cursor()->each(function ($invite){
|
||||
|
||||
if($invite->credits()->doesnthave('invitations'))
|
||||
if($invite->credit()->doesnthave('invitations'))
|
||||
$invite->credit->service()->createInvitations();
|
||||
|
||||
});
|
||||
|
@ -43,6 +43,11 @@ class CustomPaymentDriver extends BaseDriver
|
||||
return $types;
|
||||
}
|
||||
|
||||
public function init()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setPaymentMethod($payment_method_id)
|
||||
{
|
||||
$this->payment_method = $payment_method_id;
|
||||
@ -101,4 +106,9 @@ class CustomPaymentDriver extends BaseDriver
|
||||
{
|
||||
// Driver doesn't support this feature.
|
||||
}
|
||||
|
||||
public function getClientRequiredFields(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ class ApplyNumber extends AbstractService
|
||||
|
||||
public function run()
|
||||
{
|
||||
|
||||
if ($this->invoice->number != '') {
|
||||
return $this->invoice;
|
||||
}
|
||||
@ -45,7 +46,7 @@ class ApplyNumber extends AbstractService
|
||||
$this->trySaving();
|
||||
break;
|
||||
case 'when_sent':
|
||||
if ($this->invoice->status_id == Invoice::STATUS_SENT) {
|
||||
if ($this->invoice->status_id >= Invoice::STATUS_SENT) {
|
||||
$this->trySaving();
|
||||
}
|
||||
break;
|
||||
|
@ -85,7 +85,11 @@ class UpdateInvoicePayment
|
||||
|
||||
if($invoice->is_proforma)
|
||||
{
|
||||
|
||||
if(strlen($invoice->number) > 1 && str_starts_with($invoice->number,"####"))
|
||||
$invoice->number = '';
|
||||
|
||||
|
||||
$invoice->is_proforma = false;
|
||||
|
||||
$invoice->service()
|
||||
|
@ -958,7 +958,7 @@ class SubscriptionService
|
||||
$invoice->subscription_id = $this->subscription->id;
|
||||
$invoice->client_id = $client_id;
|
||||
$invoice->is_proforma = true;
|
||||
$invoice->number = ctrans('texts.subscription') . "_" . now()->format('Y-m-d') . "_" . rand(0,100000);
|
||||
$invoice->number = "####" . ctrans('texts.subscription') . "_" . now()->format('Y-m-d') . "_" . rand(0,100000);
|
||||
$line_items = $bundle->map(function ($item){
|
||||
|
||||
$line_item = new InvoiceItem;
|
||||
|
@ -11,13 +11,12 @@
|
||||
|
||||
namespace App\Transformers;
|
||||
|
||||
use App\Models\Account;
|
||||
use App\Models\BankTransaction;
|
||||
use App\Models\BankTransactionRule;
|
||||
use App\Models\Company;
|
||||
use App\Models\Expense;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\ExpenseCategory;
|
||||
use App\Transformers\VendorTransformer;
|
||||
use App\Transformers\ExpenseCateogryTransformer;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
|
||||
/**
|
||||
@ -77,6 +76,9 @@ class BankTransactionRuleTransformer extends EntityTransformer
|
||||
{
|
||||
$transformer = new ClientTransformer($this->serializer);
|
||||
|
||||
if(!$bank_transaction_rule->client)
|
||||
return null;
|
||||
|
||||
return $this->includeItem($bank_transaction_rule->expense, $transformer, Client::class);
|
||||
}
|
||||
|
||||
@ -84,7 +86,20 @@ class BankTransactionRuleTransformer extends EntityTransformer
|
||||
{
|
||||
$transformer = new VendorTransformer($this->serializer);
|
||||
|
||||
if(!$bank_transaction_rule->vendor)
|
||||
return null;
|
||||
|
||||
return $this->includeItem($bank_transaction_rule->vendor, $transformer, Vendor::class);
|
||||
}
|
||||
|
||||
public function includeExpenseCategory(BankTransactionRule $bank_transaction_rule)
|
||||
{
|
||||
$transformer = new ExpenseCategoryTransformer($this->serializer);
|
||||
|
||||
if(!$bank_transaction_rule->expense_cateogry)
|
||||
return null;
|
||||
|
||||
return $this->includeItem($bank_transaction_rule->expense_category, $transformer, ExpenseCategory::class);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -93,6 +93,8 @@ class ProductTransformer extends EntityTransformer
|
||||
'in_stock_quantity' => (int) $product->in_stock_quantity ?: 0,
|
||||
'stock_notification' => (bool) $product->stock_notification,
|
||||
'stock_notification_threshold' => (int) $product->stock_notification_threshold,
|
||||
'max_quantity' => (int) $product->max_quantity,
|
||||
'product_image' => (string) $product->product_image ?: '',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -14,8 +14,8 @@ return [
|
||||
'require_https' => env('REQUIRE_HTTPS', true),
|
||||
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
||||
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
||||
'app_version' => '5.5.68',
|
||||
'app_tag' => '5.5.68',
|
||||
'app_version' => '5.5.69',
|
||||
'app_tag' => '5.5.69',
|
||||
'minimum_client_version' => '5.0.16',
|
||||
'terms_version' => '1.0.1',
|
||||
'api_secret' => env('API_SECRET', ''),
|
||||
|
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('products', function (Blueprint $table){
|
||||
$table->unsignedInteger("max_quantity")->nullable();
|
||||
$table->string("product_image", 191)->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
};
|
2
public/js/clients/quotes/approve.js
vendored
2
public/js/clients/quotes/approve.js
vendored
@ -1,2 +1,2 @@
|
||||
/*! For license information please see approve.js.LICENSE.txt */
|
||||
(()=>{function e(e,t){for(var n=0;n<t.length;n++){var u=t[n];u.enumerable=u.enumerable||!1,u.configurable=!0,"value"in u&&(u.writable=!0),Object.defineProperty(e,u.key,u)}}var t=function(){function t(e,n,u){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),this.shouldDisplaySignature=e,this.shouldDisplayTerms=n,this.shouldDisplayUserInput=u,this.termsAccepted=!1}var n,u,a;return n=t,(u=[{key:"submitForm",value:function(){document.getElementById("approve-form").submit()}},{key:"displaySignature",value:function(){document.getElementById("displaySignatureModal").removeAttribute("style");var e=new SignaturePad(document.getElementById("signature-pad"),{penColor:"rgb(0, 0, 0)"});e.onEnd=function(){document.getElementById("signature-next-step").disabled=!1},this.signaturePad=e}},{key:"displayTerms",value:function(){document.getElementById("displayTermsModal").removeAttribute("style")}},{key:"displayInput",value:function(){document.getElementById("displayInputModal").removeAttribute("style")}},{key:"handle",value:function(){var e=this;document.getElementById("signature-next-step").disabled=!0,document.getElementById("close_button").addEventListener("click",(function(){var e=document.getElementById("approve-button");e&&(e.disabled=!1)})),document.getElementById("hide_close").addEventListener("click",(function(){var e=document.getElementById("approve-button");e&&(e.disabled=!1)})),document.getElementById("approve-button").addEventListener("click",(function(){e.shouldDisplaySignature||e.shouldDisplayTerms||!e.shouldDisplayUserInput||(e.displayInput(),document.getElementById("input-next-step").addEventListener("click",(function(){document.querySelector('input[name="user_input"').value=document.getElementById("user_input").value,e.termsAccepted=!0,e.submitForm()}))),e.shouldDisplayUserInput&&e.displayInput(),e.shouldDisplaySignature&&e.shouldDisplayTerms&&(e.displaySignature(),document.getElementById("signature-next-step").addEventListener("click",(function(){e.displayTerms(),document.getElementById("accept-terms-button").addEventListener("click",(function(){document.querySelector('input[name="signature"').value=e.signaturePad.toDataURL(),document.querySelector('input[name="user_input"').value=document.getElementById("user_input").value,e.termsAccepted=!0,e.submitForm()}))}))),e.shouldDisplaySignature&&!e.shouldDisplayTerms&&(e.displaySignature(),document.getElementById("signature-next-step").addEventListener("click",(function(){document.querySelector('input[name="signature"').value=e.signaturePad.toDataURL(),document.querySelector('input[name="user_input"').value=document.getElementById("user_input").value,e.submitForm()}))),!e.shouldDisplaySignature&&e.shouldDisplayTerms&&(e.displayTerms(),document.getElementById("accept-terms-button").addEventListener("click",(function(){e.termsAccepted=!0,e.submitForm()}))),e.shouldDisplaySignature||e.shouldDisplayTerms||!e.shouldDisplayUserInput||e.submitForm()}))}}])&&e(n.prototype,u),a&&e(n,a),Object.defineProperty(n,"prototype",{writable:!1}),t}(),n=document.querySelector('meta[name="require-quote-signature"]').content,u=document.querySelector('meta[name="show-quote-terms"]').content,a=document.querySelector('meta[name="accept-user-input"]').content;new t(Boolean(+n),Boolean(+u),Boolean(+a)).handle()})();
|
||||
(()=>{function e(e,t){for(var n=0;n<t.length;n++){var u=t[n];u.enumerable=u.enumerable||!1,u.configurable=!0,"value"in u&&(u.writable=!0),Object.defineProperty(e,u.key,u)}}var t=function(){function t(e,n,u){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),this.shouldDisplaySignature=e,this.shouldDisplayTerms=n,this.shouldDisplayUserInput=u,this.termsAccepted=!1}var n,u,a;return n=t,(u=[{key:"submitForm",value:function(){document.getElementById("approve-form").submit()}},{key:"displaySignature",value:function(){document.getElementById("displaySignatureModal").removeAttribute("style");var e=new SignaturePad(document.getElementById("signature-pad"),{penColor:"rgb(0, 0, 0)"});e.onEnd=function(){document.getElementById("signature-next-step").disabled=!1},this.signaturePad=e}},{key:"displayTerms",value:function(){document.getElementById("displayTermsModal").removeAttribute("style")}},{key:"displayInput",value:function(){document.getElementById("displayInputModal").removeAttribute("style")}},{key:"handle",value:function(){var e=this;document.getElementById("signature-next-step").disabled=!0,document.getElementById("close_button").addEventListener("click",(function(){var e=document.getElementById("approve-button");e&&(e.disabled=!1)})),document.getElementById("hide_close").addEventListener("click",(function(){var e=document.getElementById("approve-button");e&&(e.disabled=!1)})),document.getElementById("approve-button").addEventListener("click",(function(){e.shouldDisplaySignature||e.shouldDisplayTerms||!e.shouldDisplayUserInput||(e.displayInput(),document.getElementById("input-next-step").addEventListener("click",(function(){document.querySelector('input[name="user_input"').value=document.getElementById("user_input").value,e.termsAccepted=!0,e.submitForm()}))),e.shouldDisplayUserInput&&e.displayInput(),e.shouldDisplaySignature&&e.shouldDisplayTerms&&(e.displaySignature(),document.getElementById("signature-next-step").addEventListener("click",(function(){e.displayTerms(),document.getElementById("accept-terms-button").addEventListener("click",(function(){document.querySelector('input[name="signature"').value=e.signaturePad.toDataURL(),document.querySelector('input[name="user_input"').value=document.getElementById("user_input").value,e.termsAccepted=!0,e.submitForm()}))}))),e.shouldDisplaySignature&&!e.shouldDisplayTerms&&(e.displaySignature(),document.getElementById("signature-next-step").addEventListener("click",(function(){document.querySelector('input[name="signature"').value=e.signaturePad.toDataURL(),document.querySelector('input[name="user_input"').value=document.getElementById("user_input").value,e.submitForm()}))),!e.shouldDisplaySignature&&e.shouldDisplayTerms&&(e.displayTerms(),document.getElementById("accept-terms-button").addEventListener("click",(function(){e.termsAccepted=!0,e.submitForm()}))),e.shouldDisplaySignature||e.shouldDisplayTerms||e.shouldDisplayUserInput||e.submitForm()}))}}])&&e(n.prototype,u),a&&e(n,a),Object.defineProperty(n,"prototype",{writable:!1}),t}(),n=document.querySelector('meta[name="require-quote-signature"]').content,u=document.querySelector('meta[name="show-quote-terms"]').content,a=document.querySelector('meta[name="accept-user-input"]').content;new t(Boolean(+n),Boolean(+u),Boolean(+a)).handle()})();
|
@ -14,7 +14,7 @@
|
||||
"/js/clients/payments/stripe-alipay.js": "/js/clients/payments/stripe-alipay.js?id=0274ab4f8d2b411f2a2fe5142301e7af",
|
||||
"/js/clients/payments/checkout-credit-card.js": "/js/clients/payments/checkout-credit-card.js?id=4bd34a0b160f6f29b3096d870ac4d308",
|
||||
"/js/clients/quotes/action-selectors.js": "/js/clients/quotes/action-selectors.js?id=6fb63bae43d077b5061f4dadfe8dffc8",
|
||||
"/js/clients/quotes/approve.js": "/js/clients/quotes/approve.js?id=61a346e1977d3a1fec3634b234baa25c",
|
||||
"/js/clients/quotes/approve.js": "/js/clients/quotes/approve.js?id=2cb18f2df99d0eca47fa34f1d652c34f",
|
||||
"/js/clients/payments/stripe-credit-card.js": "/js/clients/payments/stripe-credit-card.js?id=809de47258a681f0ffebe787dd6a9a93",
|
||||
"/js/setup/setup.js": "/js/setup/setup.js?id=27560b012f166f8b9417ced2188aab70",
|
||||
"/js/clients/payments/card-js.min.js": "/js/clients/payments/card-js.min.js?id=8ce33c3deae058ad314fb8357e5be63b",
|
||||
|
2
resources/js/clients/quotes/approve.js
vendored
2
resources/js/clients/quotes/approve.js
vendored
@ -146,7 +146,7 @@ class Approve {
|
||||
});
|
||||
}
|
||||
|
||||
if (!this.shouldDisplaySignature && !this.shouldDisplayTerms && this.shouldDisplayUserInput) {
|
||||
if (!this.shouldDisplaySignature && !this.shouldDisplayTerms && !this.shouldDisplayUserInput) {
|
||||
this.submitForm();
|
||||
}
|
||||
});
|
||||
|
@ -36,9 +36,9 @@
|
||||
@if(!empty($subscription->recurring_product_ids))
|
||||
@foreach($recurring_products as $index => $product)
|
||||
<li class="flex py-6">
|
||||
@if(filter_var($product->custom_value1, FILTER_VALIDATE_URL))
|
||||
@if(filter_var($product->product_image, FILTER_VALIDATE_URL))
|
||||
<div class="h-24 w-24 flex-shrink-0 overflow-hidden rounded-md border border-gray-200 mr-2">
|
||||
<img src="{{$product->custom_value1}}" alt="" class="h-full w-full object-cover object-center p-2">
|
||||
<img src="{{$product->product_image}}" alt="" class="h-full w-full object-cover object-center p-2">
|
||||
</div>
|
||||
@endif
|
||||
<div class="ml-0 flex flex-1 flex-col">
|
||||
@ -74,7 +74,7 @@
|
||||
@endfor
|
||||
}
|
||||
@else
|
||||
@for ($i = 2; $i <= ($subscription->use_inventory_management ? min($product->in_stock_quantity, max(100,$product->custom_value2)) : max(100,$product->custom_value2)); $i++)
|
||||
@for ($i = 2; $i <= ($subscription->use_inventory_management ? min($product->in_stock_quantity, max(100,$product->max_quantity)) : max(100,$product->max_quantity)); $i++)
|
||||
<option value="{{$i}}">{{$i}}</option>
|
||||
@endfor
|
||||
@endif
|
||||
@ -96,9 +96,9 @@
|
||||
@if(!empty($subscription->product_ids))
|
||||
@foreach($products as $product)
|
||||
<li class="flex py-6">
|
||||
@if(filter_var($product->custom_value1, FILTER_VALIDATE_URL))
|
||||
@if(filter_var($product->product_image, FILTER_VALIDATE_URL))
|
||||
<div class="h-24 w-24 flex-shrink-0 overflow-hidden rounded-md border border-gray-200 mr-2">
|
||||
<img src="{{$product->custom_value1}}" alt="" class="h-full w-full object-cover object-center p-2">
|
||||
<img src="{{$product->product_image}}" alt="" class="h-full w-full object-cover object-center p-2">
|
||||
</div>
|
||||
@endif
|
||||
<div class="ml-0 flex flex-1 flex-col">
|
||||
@ -135,9 +135,9 @@
|
||||
@if(!empty($subscription->optional_recurring_product_ids))
|
||||
@foreach($optional_recurring_products as $index => $product)
|
||||
<li class="flex py-6">
|
||||
@if(filter_var($product->custom_value1, FILTER_VALIDATE_URL))
|
||||
@if(filter_var($product->product_image, FILTER_VALIDATE_URL))
|
||||
<div class="h-24 w-24 flex-shrink-0 overflow-hidden rounded-md border border-gray-200 mr-2">
|
||||
<img src="{{$product->custom_value1}}" alt="" class="h-full w-full object-cover object-center p-2">
|
||||
<img src="{{$product->product_image}}" alt="" class="h-full w-full object-cover object-center p-2">
|
||||
</div>
|
||||
@endif
|
||||
<div class="ml-0 flex flex-1 flex-col">
|
||||
@ -148,7 +148,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-between text-sm mt-1">
|
||||
@if(is_numeric($product->custom_value2))
|
||||
@if(is_numeric($product->max_quantity))
|
||||
<p class="text-gray-500 w-3/4"></p>
|
||||
<div class="flex place-content-end">
|
||||
@if($subscription->use_inventory_management && $product->in_stock_quantity == 0)
|
||||
@ -162,7 +162,7 @@
|
||||
@endif
|
||||
>
|
||||
<option value="0" selected="selected">0</option>
|
||||
@for ($i = 1; $i <= ($subscription->use_inventory_management ? min($product->in_stock_quantity, max(100,$product->custom_value2)) : max(100,$product->custom_value2)); $i++)
|
||||
@for ($i = 1; $i <= ($subscription->use_inventory_management ? min($product->in_stock_quantity, max(100,$product->max_quantity)) : max(100,$product->max_quantity)); $i++)
|
||||
<option value="{{$i}}">{{$i}}</option>
|
||||
@endfor
|
||||
</select>
|
||||
@ -176,9 +176,9 @@
|
||||
@if(!empty($subscription->optional_product_ids))
|
||||
@foreach($optional_products as $index => $product)
|
||||
<li class="flex py-6">
|
||||
@if(filter_var($product->custom_value1, FILTER_VALIDATE_URL))
|
||||
@if(filter_var($product->product_image, FILTER_VALIDATE_URL))
|
||||
<div class="h-24 w-24 flex-shrink-0 overflow-hidden rounded-md border border-gray-200 mr-2">
|
||||
<img src="{{$product->custom_value1}}" alt="" class="h-full w-full object-cover object-center p-2">
|
||||
<img src="{{$product->product_image}}" alt="" class="h-full w-full object-cover object-center p-2">
|
||||
</div>
|
||||
@endif
|
||||
<div class="ml-0 flex flex-1 flex-col">
|
||||
@ -190,7 +190,7 @@
|
||||
<p class="mt-1 text-sm text-gray-500"></p>
|
||||
</div>
|
||||
<div class="flex justify-between text-sm mt-1">
|
||||
@if(is_numeric($product->custom_value2))
|
||||
@if(is_numeric($product->max_quantity))
|
||||
<p class="text-gray-500 w-3/4"></p>
|
||||
<div class="flex place-content-end">
|
||||
@if($subscription->use_inventory_management && $product->in_stock_quantity == 0)
|
||||
@ -200,7 +200,7 @@
|
||||
@endif
|
||||
<select wire:model.debounce.300ms="data.{{ $index }}.optional_qty" class="rounded-md border-gray-300 shadow-sm sm:text-sm">
|
||||
<option value="0" selected="selected">0</option>
|
||||
@for ($i = 1; $i <= ($subscription->use_inventory_management ? min($product->in_stock_quantity, min(100,$product->custom_value2)) : min(100,$product->custom_value2)); $i++)
|
||||
@for ($i = 1; $i <= ($subscription->use_inventory_management ? min($product->in_stock_quantity, min(100,$product->max_quantity)) : min(100,$product->max_quantity)); $i++)
|
||||
<option value="{{$i}}">{{$i}}</option>
|
||||
@endfor
|
||||
</select>
|
||||
|
@ -58,7 +58,7 @@ class TaskApiTest extends TestCase
|
||||
public function testTaskLockingGate()
|
||||
{
|
||||
$data = [
|
||||
'timelog' => [[1,2],[3,4]],
|
||||
'timelog' => [[1,2,'a'],[3,4,'d']],
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
@ -194,7 +194,7 @@ class TaskApiTest extends TestCase
|
||||
public function testTimeLogValidation3()
|
||||
{
|
||||
$data = [
|
||||
'timelog' => [["a","b"],["c","d"]],
|
||||
'timelog' => [["a","b",'d'],["c","d",'d']],
|
||||
];
|
||||
|
||||
try {
|
||||
@ -213,7 +213,7 @@ class TaskApiTest extends TestCase
|
||||
public function testTimeLogValidation4()
|
||||
{
|
||||
$data = [
|
||||
'timelog' => [[1,2],[3,0]],
|
||||
'timelog' => [[1,2,'d'],[3,0,'d']],
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
@ -232,8 +232,8 @@ class TaskApiTest extends TestCase
|
||||
public function testStartTask()
|
||||
{
|
||||
$log = [
|
||||
[2, 1],
|
||||
[10, 20],
|
||||
[2, 1,'d'],
|
||||
[10, 20,'d'],
|
||||
];
|
||||
|
||||
$last = end($log);
|
||||
|
Loading…
x
Reference in New Issue
Block a user