mirror of
https://github.com/InvoiceShelf/InvoiceShelf.git
synced 2026-04-14 00:34:05 +00:00
Clone estimates (#97)
* Clone estimates * Clone estimate test feature * Resolve namespace * Fix string to int for Carbon * Fix homes routes and default queue key * Move dropdown item below View and use the propper translation key
This commit is contained in:
@@ -23,7 +23,7 @@ DB_PASSWORD="invoiceshelf"
|
||||
|
||||
BROADCAST_CONNECTION=log
|
||||
CACHE_STORE=file
|
||||
QUEUE_DRIVER=sync
|
||||
QUEUE_CONNECTION=sync
|
||||
SESSION_DRIVER=cookie
|
||||
SESSION_LIFETIME=1440
|
||||
SESSION_ENCRYPT=false
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\V1\Admin\Estimate;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\EstimateResource;
|
||||
use App\Models\CompanySetting;
|
||||
use App\Models\Estimate;
|
||||
use App\Services\SerialNumberFormatter;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Vinkla\Hashids\Facades\Hashids;
|
||||
|
||||
class CloneEstimateController extends Controller
|
||||
{
|
||||
/**
|
||||
* Mail a specific invoice to the corresponding customer's email address.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(Request $request, Estimate $estimate)
|
||||
{
|
||||
$this->authorize('create', Estimate::class);
|
||||
|
||||
$date = Carbon::now();
|
||||
|
||||
$serial = (new SerialNumberFormatter())
|
||||
->setModel($estimate)
|
||||
->setCompany($estimate->company_id)
|
||||
->setCustomer($estimate->customer_id)
|
||||
->setNextNumbers();
|
||||
|
||||
$due_date = null;
|
||||
$dueDateEnabled = CompanySetting::getSetting(
|
||||
'estimate_set_expiry_date_automatically',
|
||||
$request->header('company')
|
||||
);
|
||||
|
||||
if ($dueDateEnabled === 'YES') {
|
||||
$dueDateDays = intval(CompanySetting::getSetting(
|
||||
'estimate_expiry_date_days',
|
||||
$request->header('company')
|
||||
));
|
||||
$due_date = Carbon::now()->addDays($dueDateDays)->format('Y-m-d');
|
||||
}
|
||||
|
||||
$exchange_rate = $estimate->exchange_rate;
|
||||
|
||||
$newEstimate = Estimate::create([
|
||||
'estimate_date' => $date->format('Y-m-d'),
|
||||
'expiry_date' => $due_date,
|
||||
'estimate_number' => $serial->getNextNumber(),
|
||||
'sequence_number' => $serial->nextSequenceNumber,
|
||||
'customer_sequence_number' => $serial->nextCustomerSequenceNumber,
|
||||
'reference_number' => $estimate->reference_number,
|
||||
'customer_id' => $estimate->customer_id,
|
||||
'company_id' => $request->header('company'),
|
||||
'template_name' => $estimate->template_name,
|
||||
'status' => Estimate::STATUS_DRAFT,
|
||||
'sub_total' => $estimate->sub_total,
|
||||
'discount' => $estimate->discount,
|
||||
'discount_type' => $estimate->discount_type,
|
||||
'discount_val' => $estimate->discount_val,
|
||||
'total' => $estimate->total,
|
||||
'due_amount' => $estimate->total,
|
||||
'tax_per_item' => $estimate->tax_per_item,
|
||||
'discount_per_item' => $estimate->discount_per_item,
|
||||
'tax' => $estimate->tax,
|
||||
'notes' => $estimate->notes,
|
||||
'exchange_rate' => $exchange_rate,
|
||||
'base_total' => $estimate->total * $exchange_rate,
|
||||
'base_discount_val' => $estimate->discount_val * $exchange_rate,
|
||||
'base_sub_total' => $estimate->sub_total * $exchange_rate,
|
||||
'base_tax' => $estimate->tax * $exchange_rate,
|
||||
'base_due_amount' => $estimate->total * $exchange_rate,
|
||||
'currency_id' => $estimate->currency_id,
|
||||
'sales_tax_type' => $estimate->sales_tax_type,
|
||||
'sales_tax_address_type' => $estimate->sales_tax_address_type,
|
||||
]);
|
||||
|
||||
$newEstimate->unique_hash = Hashids::connection(Estimate::class)->encode($newEstimate->id);
|
||||
$newEstimate->save();
|
||||
$estimate->load('items.taxes');
|
||||
|
||||
$estimateItems = $estimate->items->toArray();
|
||||
|
||||
foreach ($estimateItems as $estimateItem) {
|
||||
$estimateItem['company_id'] = $request->header('company');
|
||||
$estimateItem['name'] = $estimateItem['name'];
|
||||
$estimateItem['exchange_rate'] = $exchange_rate;
|
||||
$estimateItem['base_price'] = $estimateItem['price'] * $exchange_rate;
|
||||
$estimateItem['base_discount_val'] = $estimateItem['discount_val'] * $exchange_rate;
|
||||
$estimateItem['base_tax'] = $estimateItem['tax'] * $exchange_rate;
|
||||
$estimateItem['base_total'] = $estimateItem['total'] * $exchange_rate;
|
||||
|
||||
$item = $newEstimate->items()->create($estimateItem);
|
||||
|
||||
if (array_key_exists('taxes', $estimateItem) && $estimateItem['taxes']) {
|
||||
foreach ($estimateItem['taxes'] as $tax) {
|
||||
$tax['company_id'] = $request->header('company');
|
||||
|
||||
if ($tax['amount']) {
|
||||
$item->taxes()->create($tax);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($estimate->taxes) {
|
||||
foreach ($estimate->taxes->toArray() as $tax) {
|
||||
$tax['company_id'] = $request->header('company');
|
||||
$newEstimate->taxes()->create($tax);
|
||||
}
|
||||
}
|
||||
|
||||
if ($estimate->fields()->exists()) {
|
||||
$customFields = [];
|
||||
|
||||
foreach ($estimate->fields as $data) {
|
||||
$customFields[] = [
|
||||
'id' => $data->custom_field_id,
|
||||
'value' => $data->defaultAnswer,
|
||||
];
|
||||
}
|
||||
|
||||
$newEstimate->addCustomFields($customFields);
|
||||
}
|
||||
|
||||
return new EstimateResource($newEstimate);
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,16 @@ class AppServiceProvider extends ServiceProvider
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const HOME = '/home';
|
||||
public const HOME = '/admin/dashboard';
|
||||
|
||||
/**
|
||||
* The path to the "customer home" route for your application.
|
||||
*
|
||||
* This is used by Laravel authentication to redirect customers after login.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const CUSTOMER_HOME = '/customer/dashboard';
|
||||
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
|
||||
@@ -304,6 +304,9 @@
|
||||
"record_payment": "تسجيل مدفوات",
|
||||
"add_estimate": "إضافة تقدير",
|
||||
"save_estimate": "حفظ التقدير",
|
||||
"cloned_successfully": "تم استنساخ العرض بنجاح",
|
||||
"clone_estimate": "استنساخ العرض",
|
||||
"confirm_clone": "سيتم استنساخ هذا العرض إلى عرض جديد",
|
||||
"confirm_conversion": "هل تريد تحويل هذا التقدير إلى فاتورة؟",
|
||||
"conversion_message": "تم إنشاء الفاتورة بنجاح",
|
||||
"confirm_send_estimate": "سيتم إرسال هذا التقدير بالبريد الإلكتروني إلى العميل",
|
||||
|
||||
@@ -304,6 +304,9 @@
|
||||
"record_payment": "Zaznamenat platbu",
|
||||
"add_estimate": "Přidat nabídku",
|
||||
"save_estimate": "Uložit nabídku",
|
||||
"cloned_successfully": "Devis úspěšně zkopírován",
|
||||
"clone_estimate": "Klonovat devis",
|
||||
"confirm_clone": "Tento devis bude zkopírován do nového devisu",
|
||||
"confirm_conversion": "Tento odhad bude použit k vytvoření nové faktury.",
|
||||
"conversion_message": "Faktura byla úspěšně vytvořena",
|
||||
"confirm_send_estimate": "Tento odhad bude zaslán e-mailem zákazníkovi",
|
||||
|
||||
@@ -304,6 +304,9 @@
|
||||
"record_payment": "Zahlung erfassen",
|
||||
"add_estimate": "Angebote hinzufügen",
|
||||
"save_estimate": "Angebot speichern",
|
||||
"cloned_successfully": "Angebot erfolgreich geklont",
|
||||
"clone_estimate": "Angebot klonen",
|
||||
"confirm_clone": "Dieses Angebot wird in ein neues Angebot kopiert",
|
||||
"confirm_conversion": "Dieses Angebot wird verwendet, um eine neue Rechnung zu erstellen.",
|
||||
"conversion_message": "Rechnung erfolgreich erstellt",
|
||||
"confirm_send_estimate": "Das Angebot wird per E-Mail an den Kunden gesendet",
|
||||
|
||||
@@ -304,6 +304,9 @@
|
||||
"record_payment": "Καταγραφή Πληρωμής",
|
||||
"add_estimate": "Νέα Εκτίμηση",
|
||||
"save_estimate": "Νέα Εκτίμηση",
|
||||
"cloned_successfully": "Η προσφορά κλωνοποιήθηκε με επιτυχία",
|
||||
"clone_estimate": "Κλωνοποίηση προσφοράς",
|
||||
"confirm_clone": "Αυτή η προσφορά θα κλωνοποιηθεί σε μια νέα προσφορά",
|
||||
"confirm_conversion": "Αυτή η εκτίμηση θα χρησιμοποιηθεί για τη δημιουργία ενός νέου τιμολογίου.",
|
||||
"conversion_message": "Το τιμολόγιο κλωνοποιήθηκε επιτυχώς",
|
||||
"confirm_send_estimate": "Αυτό το τιμολόγιο θα αποσταλεί μέσω email στον πελάτη",
|
||||
|
||||
@@ -323,6 +323,9 @@
|
||||
"record_payment": "Record Payment",
|
||||
"add_estimate": "Add Estimate",
|
||||
"save_estimate": "Save Estimate",
|
||||
"cloned_successfully": "Estimate cloned successfully",
|
||||
"clone_estimate": "Clone Estimate",
|
||||
"confirm_clone": "This Estimate will be cloned into a new Estimate",
|
||||
"confirm_conversion": "This estimate will be used to create a new Invoice.",
|
||||
"conversion_message": "Invoice created successful",
|
||||
"confirm_send_estimate": "This estimate will be sent via email to the customer",
|
||||
|
||||
@@ -304,6 +304,9 @@
|
||||
"record_payment": "Registro de pago",
|
||||
"add_estimate": "Agregar presupuesto",
|
||||
"save_estimate": "Guardar presupuesto",
|
||||
"cloned_successfully": "Presupuesto clonado con éxito",
|
||||
"clone_estimate": "Clonar presupuesto",
|
||||
"confirm_clone": "Este presupuesto será clonado en un nuevo presupuesto",
|
||||
"confirm_conversion": "¿Quiere convertir este presupuesto en una factura?",
|
||||
"conversion_message": "Conversión exitosa",
|
||||
"confirm_send_estimate": "Este presupuesto se enviará por correo electrónico al cliente",
|
||||
|
||||
@@ -323,6 +323,9 @@
|
||||
"record_payment": "Enregistrer un paiement",
|
||||
"add_estimate": "Nouveau devis",
|
||||
"save_estimate": "Enregistrer",
|
||||
"cloned_successfully": "Devis dupliqué avec succès",
|
||||
"clone_estimate": "Dupliquer le devis",
|
||||
"confirm_clone": "Ce devis sera dupliqué dans un nouveau devis",
|
||||
"confirm_conversion": "Ce devis sera utilisé pour créer une nouvelle facture.",
|
||||
"conversion_message": "Conversion réussie",
|
||||
"confirm_send_estimate": "Ce devis sera envoyée par email au client",
|
||||
|
||||
@@ -304,6 +304,9 @@
|
||||
"record_payment": "Registra Pagamento",
|
||||
"add_estimate": "Aggiungi Preventivo",
|
||||
"save_estimate": "Salva Preventivo",
|
||||
"cloned_successfully": "Preventivo clonato con successo",
|
||||
"clone_estimate": "Clonare preventivo",
|
||||
"confirm_clone": "Questo preventivo sarà clonato in un nuovo preventivo",
|
||||
"confirm_conversion": "Questo preventivo verrà usato per generare una nuova fattura.",
|
||||
"conversion_message": "Fattura creata",
|
||||
"confirm_send_estimate": "Questo preventivo verrà inviato al cliente via mail",
|
||||
|
||||
@@ -304,6 +304,9 @@
|
||||
"record_payment": "Record Payment",
|
||||
"add_estimate": "Add Estimate",
|
||||
"save_estimate": "Save Estimate",
|
||||
"cloned_successfully": "見積もりが正常にクローンされました",
|
||||
"clone_estimate": "見積もりをクローン",
|
||||
"confirm_clone": "この見積もりは新しい見積もりにクローンされます",
|
||||
"confirm_conversion": "This estimate will be used to create a new Invoice.",
|
||||
"conversion_message": "Invoice created successful",
|
||||
"confirm_send_estimate": "This estimate will be sent via email to the customer",
|
||||
|
||||
@@ -258,6 +258,9 @@
|
||||
"record_payment": "기록 지불",
|
||||
"add_estimate": "견적 추가",
|
||||
"save_estimate": "견적 저장",
|
||||
"cloned_successfully": "견적이 성공적으로 복제되었습니다",
|
||||
"clone_estimate": "견적 복제",
|
||||
"confirm_clone": "이 견적은 새로운 견적으로 복제될 것입니다",
|
||||
"confirm_conversion": "이 견적은 새 인보이스를 만드는 데 사용됩니다.",
|
||||
"conversion_message": "인보이스가 성공적으로 생성되었습니다.",
|
||||
"confirm_send_estimate": "이 견적은 이메일을 통해 고객에게 전송됩니다.",
|
||||
|
||||
@@ -304,6 +304,9 @@
|
||||
"record_payment": "Izveidot maksājumu",
|
||||
"add_estimate": "Pievienot aprēķinu",
|
||||
"save_estimate": "Saglabāt aprēķinu",
|
||||
"cloned_successfully": "Piedāvājums veiksmīgi klonēts",
|
||||
"clone_estimate": "Klonēt piedāvājumu",
|
||||
"confirm_clone": "Šis piedāvājums tiks klonēts jaunā piedāvājumā",
|
||||
"confirm_conversion": "Šis aprēķins tiks izmantots, lai izveidotu jaunu rēķinu.",
|
||||
"conversion_message": "Rēķins izveidots veiksmīgi",
|
||||
"confirm_send_estimate": "Šis aprēķins tiks nosūtīts klientam e-pastā",
|
||||
|
||||
@@ -304,6 +304,9 @@
|
||||
"record_payment": "Betaling registreren",
|
||||
"add_estimate": "Offerte toevoegen",
|
||||
"save_estimate": "Bewaar offerte",
|
||||
"cloned_successfully": "Offerte succesvol gekloond",
|
||||
"clone_estimate": "Offerte klonen",
|
||||
"confirm_clone": "Deze offerte zal worden gekopieerd naar een nieuwe offerte",
|
||||
"confirm_conversion": "Deze offerte wordt gebruikt om een nieuwe factuur te maken.",
|
||||
"conversion_message": "Factuur gemaakt",
|
||||
"confirm_send_estimate": "Deze offerte wordt via e-mail naar de klant gestuurd",
|
||||
|
||||
@@ -304,6 +304,9 @@
|
||||
"record_payment": "Zarejestruj płatność",
|
||||
"add_estimate": "Dodaj ofertę",
|
||||
"save_estimate": "Zapisz ofertę",
|
||||
"cloned_successfully": "Oferta została pomyślnie sklonowana",
|
||||
"clone_estimate": "Sklonuj ofertę",
|
||||
"confirm_clone": "Ta oferta zostanie sklonowana do nowej oferty",
|
||||
"confirm_conversion": "Ta oferta zostanie użyta do utworzenia nowej faktury.",
|
||||
"conversion_message": "Faktura została utworzona pomyślnie",
|
||||
"confirm_send_estimate": "Ta oferta zostanie wysłana pocztą elektroniczną do kontrahenta",
|
||||
|
||||
@@ -237,6 +237,9 @@
|
||||
"record_payment": "Registro de pago",
|
||||
"add_estimate": "Adicionar orçamento",
|
||||
"save_estimate": "Salvar Orçamento",
|
||||
"cloned_successfully": "Orçamento clonado com sucesso",
|
||||
"clone_estimate": "Clonar orçamento",
|
||||
"confirm_clone": "Este orçamento será clonado em um novo orçamento",
|
||||
"confirm_conversion": "Deseja converter este orçamento em uma fatura?",
|
||||
"conversion_message": "Converção realizada com sucesso",
|
||||
"confirm_send_estimate": "Este orçamento será enviado por email ao cliente",
|
||||
|
||||
@@ -304,6 +304,9 @@
|
||||
"record_payment": "Zaznamenať Platbu",
|
||||
"add_estimate": "Vytvoriť Cenový odhad",
|
||||
"save_estimate": "Uložiť Cenový odhad",
|
||||
"cloned_successfully": "Ponuka úspešne skopírovaná",
|
||||
"clone_estimate": "Klonovať ponuku",
|
||||
"confirm_clone": "Táto ponuka bude skopírovaná do novej ponuky",
|
||||
"confirm_conversion": "Tento cenový odhad bude použitý k vytvoreniu novej Faktúry.",
|
||||
"conversion_message": "Faktúra úspešne vytvorená",
|
||||
"confirm_send_estimate": "Tento Cenový odhad bude odoslaný zákazníkovi prostredníctvom e-mailu",
|
||||
|
||||
@@ -304,6 +304,9 @@
|
||||
"record_payment": "Unesi uplatu",
|
||||
"add_estimate": "Dodaj Profakturu",
|
||||
"save_estimate": "Sačuvaj Profakturu",
|
||||
"cloned_successfully": "Ponuda uspešno klonirana",
|
||||
"clone_estimate": "Kloniraj ponudu",
|
||||
"confirm_clone": "Ova ponuda će biti klonirana u novu ponudu",
|
||||
"confirm_conversion": "Detalji ove Profakture će biti iskorišćeni za pravljenje Fakture.",
|
||||
"conversion_message": "Faktura uspešno kreirana",
|
||||
"confirm_send_estimate": "Ova Profaktura će biti poslata putem Email-a klijentu",
|
||||
|
||||
@@ -304,6 +304,9 @@
|
||||
"record_payment": "Registrera betalning",
|
||||
"add_estimate": "Lägg till kostnadsförslag",
|
||||
"save_estimate": "Spara kostnadsförslag",
|
||||
"cloned_successfully": "Offert klonades framgångsrikt",
|
||||
"clone_estimate": "Klona offert",
|
||||
"confirm_clone": "Denna offert kommer att klonas till en ny offert",
|
||||
"confirm_conversion": "Detta kostnadsförslag används för att skapa ny faktura.",
|
||||
"conversion_message": "Faktura skapades",
|
||||
"confirm_send_estimate": "Detta kostnadsförslag skickas via epost till kund",
|
||||
|
||||
@@ -303,6 +303,9 @@
|
||||
"record_payment": "บันทึกการชำระเงิน",
|
||||
"add_estimate": "เพิ่มค่าใบเสนอราคา",
|
||||
"save_estimate": "บันทึกใบเสนอราคา",
|
||||
"cloned_successfully": "โคลนข้อเสนอสำเร็จ",
|
||||
"clone_estimate": "โคลนข้อเสนอ",
|
||||
"confirm_clone": "ข้อเสนอนี้จะถูกโคลนเป็นข้อเสนอใหม่",
|
||||
"confirm_conversion": "ใบเสนอราคานี้จะใช้ในการสร้างใบวางบิลใหม่",
|
||||
"conversion_message": "ใบวางบิลที่สร้างเสร็จสมบูรณ์",
|
||||
"confirm_send_estimate": "ใบเสนอราคานี้จะถูกส่งผ่านทางอีเมลถึงลูกค้า",
|
||||
|
||||
@@ -62,6 +62,18 @@
|
||||
</BaseDropdownItem>
|
||||
</router-link>
|
||||
|
||||
<!-- Clone Estimate into new estimate -->
|
||||
<BaseDropdownItem
|
||||
v-if="userStore.hasAbilities(abilities.CREATE_ESTIMATE)"
|
||||
@click="cloneEstimateData(row)"
|
||||
>
|
||||
<BaseIcon
|
||||
name="DocumentTextIcon"
|
||||
class="w-5 h-5 mr-3 text-gray-400 group-hover:text-gray-500"
|
||||
/>
|
||||
{{ $t('estimates.clone_estimate') }}
|
||||
</BaseDropdownItem>
|
||||
|
||||
<!-- Convert into Invoice -->
|
||||
<BaseDropdownItem
|
||||
v-if="userStore.hasAbilities(abilities.CREATE_INVOICE)"
|
||||
@@ -334,4 +346,24 @@ function copyPdfUrl() {
|
||||
message: t('general.copied_pdf_url_clipboard'),
|
||||
})
|
||||
}
|
||||
|
||||
async function cloneEstimateData(data) {
|
||||
dialogStore
|
||||
.openDialog({
|
||||
title: t('general.are_you_sure'),
|
||||
message: t('estimates.confirm_clone'),
|
||||
yesLabel: t('general.ok'),
|
||||
noLabel: t('general.cancel'),
|
||||
variant: 'primary',
|
||||
hideNoButton: false,
|
||||
size: 'lg',
|
||||
})
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
estimateStore.cloneEstimate(data).then((res) => {
|
||||
router.push(`/admin/estimates/${res.data.data.id}/edit`)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -329,6 +329,25 @@ export const useEstimateStore = (useWindow = false) => {
|
||||
})
|
||||
},
|
||||
|
||||
cloneEstimate(data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios
|
||||
.post(`/api/v1/estimates/${data.id}/clone`, data)
|
||||
.then((response) => {
|
||||
const notificationStore = useNotificationStore()
|
||||
notificationStore.showNotification({
|
||||
type: 'success',
|
||||
message: global.t('estimates.cloned_successfully'),
|
||||
})
|
||||
resolve(response)
|
||||
})
|
||||
.catch((err) => {
|
||||
handleError(err)
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
markAsAccepted(data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios
|
||||
|
||||
@@ -12,6 +12,7 @@ use App\Http\Controllers\V1\Admin\Customer\CustomerStatsController;
|
||||
use App\Http\Controllers\V1\Admin\CustomField\CustomFieldsController;
|
||||
use App\Http\Controllers\V1\Admin\Dashboard\DashboardController;
|
||||
use App\Http\Controllers\V1\Admin\Estimate\ChangeEstimateStatusController;
|
||||
use App\Http\Controllers\V1\Admin\Estimate\CloneEstimateController;
|
||||
use App\Http\Controllers\V1\Admin\Estimate\ConvertEstimateController;
|
||||
use App\Http\Controllers\V1\Admin\Estimate\EstimatesController;
|
||||
use App\Http\Controllers\V1\Admin\Estimate\EstimateTemplatesController;
|
||||
@@ -285,6 +286,8 @@ Route::prefix('/v1')->group(function () {
|
||||
|
||||
Route::post('/estimates/{estimate}/send', SendEstimateController::class);
|
||||
|
||||
Route::post('/estimates/{estimate}/clone', CloneEstimateController::class);
|
||||
|
||||
Route::post('/estimates/{estimate}/status', ChangeEstimateStatusController::class);
|
||||
|
||||
Route::post('/estimates/{estimate}/convert-to-invoice', ConvertEstimateController::class);
|
||||
|
||||
@@ -65,6 +65,18 @@ test('create estimate', function () {
|
||||
]);
|
||||
});
|
||||
|
||||
test('clone estimate', function () {
|
||||
|
||||
$estimate = Estimate::factory()->create();
|
||||
|
||||
$beforeCount = Estimate::count();
|
||||
|
||||
$response = $this->post("/api/v1/estimates/{$estimate->id}/clone");
|
||||
|
||||
$this->assertDatabaseCount('estimates', $beforeCount + 1);
|
||||
|
||||
});
|
||||
|
||||
test('store validates using a form request', function () {
|
||||
$this->assertActionUsesFormRequest(
|
||||
EstimatesController::class,
|
||||
|
||||
Reference in New Issue
Block a user