Files
itflow/agent/modals/quote/quote_copy.php
johnnyq 2fcdd6006b Invoices, quotes and recurring invoices makeover stage 4: quote lines billed one time or each month, quarter or year with a Billed choice on the add-a-line row and in Edit Line, quotes grouped into One-time, Each month, Each quarter and Each year with a total for each on the page, PDF and client view, lines dragged within their own group, Start Billing on accepted quotes putting one-time lines on a draft invoice due on the client's terms and each recurring part on a new recurring invoice from a chosen date, emailed or left as drafts, or added to one of the client's recurring invoices of the same frequency, with an option to bill the first period on the invoice, an Invoiced as card on the quote linking every invoice and recurring invoice it became including ones it added lines to, From links back on invoices and recurring invoices, monthly amounts in the quotes list and its totals, search, client portal, quote email, Send and Copy windows, quotes export and client export, and Quotes Pipeline valuing quotes at up front plus a year of recurring lines. Fixes Make Invoice invoicing a quote twice or one never accepted, and its audit entry using the current quote prefix instead of the quote's own. Adds DB 2.9.3 with item_frequency, quote_monthly_amount, invoice_quote_id and recurring_invoice_quote_id, linking invoices to their quotes from history, quoteConvert() as the one invoicing path claiming the quote in a transaction, quoteLineGroups(), quoteAmountText() and quoteMadeFrom(), reportCsv() totals written as given, and updates the 26.11 changelog
2026-10-16 14:14:53 -04:00

77 lines
3.9 KiB
PHP

<?php
/*
* Copy a quote - a new draft with the same lines, scope, category, discount
* and notes, for this client or another, on the dates given. ?id=
*/
require_once '../../../includes/modal_header.php';
enforceUserPermission('module_sales', 2);
$doc_type = 'quote';
$doc = billingRow($doc_type, intval($_GET['id'] ?? 0));
if (!$doc) {
exit(json_encode(['error' => 'That quote no longer exists.']));
}
$client_id = intval($doc['client_id']);
enforceClientAccess();
$doc_number = billingNumber($doc_type, $doc);
$lines = count(billingItems('quote', intval($doc['quote_id'])));
$clients = [];
$sql = mysqli_query($mysqli, "SELECT client_id, client_name, client_abbreviation FROM clients WHERE client_archived_at IS NULL " . clientScopeSql('clients.client_id') . " ORDER BY client_name ASC");
while ($row = mysqli_fetch_assoc($sql)) {
$clients[] = $row;
}
ob_start();
?>
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-copy me-2"></i>Copy Quote <span class="fw-normal text-white-50 ms-1"><?= escapeHtml($doc_number) ?> &middot; <?= escapeHtml($doc['client_name']) ?></span></h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
<input type="hidden" name="quote_id" value="<?= intval($doc['quote_id']) ?>">
<div class="modal-body">
<p class="text-body-secondary small">A new draft with the same <?= $lines ?> line<?= $lines === 1 ? '' : 's' ?>, scope, discount and notes - <?= escapeHtml(quoteAmountText(quoteGroups($doc), $doc['quote_currency_code'])) ?>. Quote the same work for another client by picking them here.</p>
<div class="row g-3">
<div class="col-12">
<label class="form-label">For <strong class="text-danger">*</strong></label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-building"></i></span>
<select class="form-select select2" name="client_id" required>
<?php foreach ($clients as $client_option) { ?>
<option value="<?= intval($client_option['client_id']) ?>" <?= intval($client_option['client_id']) === $client_id ? 'selected' : '' ?><?= selectOptionClient($client_option['client_id'], $client_option['client_name'], $client_option['client_abbreviation'] ?? '') ?>><?= escapeHtml($client_option['client_name']) ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="col-sm-6">
<label class="form-label">Quote date <strong class="text-danger">*</strong></label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-calendar"></i></span>
<input type="date" class="form-control" name="date" max="2999-12-31" value="<?= date('Y-m-d') ?>" required>
</div>
</div>
<div class="col-sm-6">
<label class="form-label">Valid until <strong class="text-danger">*</strong></label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-hourglass-half"></i></span>
<input type="date" class="form-control" name="expire" min="<?= date('Y-m-d') ?>" max="2999-12-31" value="<?= date('Y-m-d', strtotime('+30 days')) ?>" required>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="add_quote_copy" class="btn btn-primary text-bold"><i class="fas fa-copy me-2"></i>Copy</button>
<button type="button" class="btn btn-light" data-bs-dismiss="modal"><i class="fas fa-times me-2"></i>Cancel</button>
</div>
</form>
<?php
require_once '../../../includes/modal_footer.php';