656 lines
26 KiB
PHP
656 lines
26 KiB
PHP
<?php
|
|
session_start();
|
|
require '../config.php';
|
|
require '../include_header.php';
|
|
?>
|
|
|
|
<body>
|
|
<?php require '../include_topbar.php'; ?>
|
|
<?php require '../include_master_sidebar.php'; ?>
|
|
|
|
<main id="content" class="content py-15">
|
|
<div class="container-fluid">
|
|
|
|
<div class="row mb-5">
|
|
<div class="col-12">
|
|
<div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center gap-3">
|
|
<div>
|
|
<h1 class="fs-3 mb-1">Account Formulas</h1>
|
|
<p class="mb-0 text-muted">Posting patterns for document journal entries</p>
|
|
</div>
|
|
<button class="btn btn-primary" onclick="show_formula_form()">
|
|
<i class="ti ti-plus me-1"></i>New Formula
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<ul class="nav nav-tabs mb-4" id="account_formula_tabs">
|
|
<li class="nav-item">
|
|
<button class="nav-link active" id="tab_formulas" type="button" onclick="show_account_tab('formulas')">Formulas</button>
|
|
</li>
|
|
<li class="nav-item">
|
|
<button class="nav-link" id="tab_product_accounts" type="button" onclick="show_account_tab('product_accounts')">Product Accounts</button>
|
|
</li>
|
|
</ul>
|
|
|
|
<div class="row g-5 d-none" id="formula_form">
|
|
<div class="col-lg-8">
|
|
<div class="card mb-5">
|
|
<div class="card-body p-5">
|
|
<input type="hidden" id="id">
|
|
<h2 class="fs-5 mb-4">Formula Setup</h2>
|
|
<div class="row g-4">
|
|
<div class="col-lg-6">
|
|
<label class="form-label">Formula Name</label>
|
|
<input type="text" id="formula_name" class="form-control" placeholder="e.g. Standard Sales Invoice">
|
|
</div>
|
|
<div class="col-lg-4">
|
|
<label class="form-label">Document Type</label>
|
|
<select id="document_type" class="form-select">
|
|
<option value="sales_invoice">Sales Invoice</option>
|
|
<option value="sales_credit_note">Sales Credit Note</option>
|
|
<option value="receipt">Receipt</option>
|
|
<option value="purchase_invoice">Purchase Invoice</option>
|
|
<option value="supplier_credit_note">Supplier Credit Note</option>
|
|
<option value="payment">Payment</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-lg-2">
|
|
<label class="form-label">Status</label>
|
|
<select id="status" class="form-select">
|
|
<option value="1">Active</option>
|
|
<option value="0">Inactive</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-12">
|
|
<label class="form-label">Description</label>
|
|
<textarea id="description" class="form-control" rows="2"></textarea>
|
|
</div>
|
|
<div class="col-12">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="is_default" value="1">
|
|
<label class="form-check-label" for="is_default">Use as default for this document type</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-body p-5">
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<h2 class="fs-5 mb-0">Formula Items</h2>
|
|
<button class="btn btn-sm btn-outline-primary" onclick="add_item_row()">
|
|
<i class="ti ti-plus me-1"></i>Add Item
|
|
</button>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table mb-0">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th style="width:100px;">Side</th>
|
|
<th>Account</th>
|
|
<th style="width:150px;">Value</th>
|
|
<th>Description</th>
|
|
<th style="width:40px;"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="item_tbody"></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-lg-4">
|
|
<div class="card mb-5">
|
|
<div class="card-body p-4">
|
|
<h2 class="fs-5 mb-3">Available Values</h2>
|
|
<div class="small d-flex flex-column gap-2">
|
|
<div><span class="fw-semibold">grand_total</span><div class="text-muted">Final document total</div></div>
|
|
<div><span class="fw-semibold">total</span><div class="text-muted">Subtotal less discount plus shipping</div></div>
|
|
<div><span class="fw-semibold">tax</span><div class="text-muted">Document tax amount</div></div>
|
|
<div><span class="fw-semibold">amount</span><div class="text-muted">Receipt or payment amount</div></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-body p-4 d-flex flex-column gap-2">
|
|
<button class="btn btn-primary w-100" onclick="save_formula()">
|
|
<i class="ti ti-device-floppy me-1"></i>Save Formula
|
|
</button>
|
|
<button class="btn btn-light w-100" onclick="hide_formula_form()">Cancel</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row" id="formula_list_section">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-body p-5">
|
|
<div class="row g-3 mb-4">
|
|
<div class="col-lg-8">
|
|
<input type="search" id="search_input" class="form-control" placeholder="Search formula or document type...">
|
|
</div>
|
|
<div class="col-lg-4">
|
|
<select id="filter_document_type" class="form-select">
|
|
<option value="">All Document Types</option>
|
|
<option value="sales_invoice">Sales Invoice</option>
|
|
<option value="sales_credit_note">Sales Credit Note</option>
|
|
<option value="receipt">Receipt</option>
|
|
<option value="purchase_invoice">Purchase Invoice</option>
|
|
<option value="supplier_credit_note">Supplier Credit Note</option>
|
|
<option value="payment">Payment</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover mb-0 table-centered" id="formula_list">
|
|
<thead class="table-primary border-light">
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Document Type</th>
|
|
<th>Items</th>
|
|
<th>Default</th>
|
|
<th>Status</th>
|
|
<th>Action</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody></tbody>
|
|
<tfoot></tfoot>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row d-none" id="product_account_section">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-body p-5">
|
|
<div class="row g-3 mb-4">
|
|
<div class="col-lg-8">
|
|
<input type="search" id="product_account_search" class="form-control" placeholder="Search product, SKU, or account...">
|
|
</div>
|
|
<div class="col-lg-4">
|
|
<select id="product_account_filter" class="form-select">
|
|
<option value="">All Products</option>
|
|
<option value="missing">Missing Mapping</option>
|
|
<option value="mapped">Mapped Sales & Purchase</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover mb-0 table-centered" id="product_account_list">
|
|
<thead class="table-primary border-light">
|
|
<tr>
|
|
<th>Product</th>
|
|
<th>SKU</th>
|
|
<th>Sales Account</th>
|
|
<th>Purchase Account</th>
|
|
<th>Status</th>
|
|
<th>Action</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody></tbody>
|
|
<tfoot></tfoot>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</main>
|
|
|
|
<div class="modal fade" id="product_account_modal" tabindex="-1" aria-hidden="true">
|
|
<div class="modal-dialog modal-lg modal-dialog-centered">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<div>
|
|
<h5 class="modal-title mb-0">Product Accounts</h5>
|
|
<div class="small text-muted" id="product_account_modal_product"></div>
|
|
</div>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<input type="hidden" id="product_account_product_id">
|
|
<input type="hidden" id="product_account_sales_code">
|
|
<input type="hidden" id="product_account_purchase_code">
|
|
<div class="row g-4">
|
|
<div class="col-md-6">
|
|
<label class="form-label">Sales Account</label>
|
|
<input type="text" class="form-control account_search" id="product_account_sales"
|
|
placeholder="Search account..." autocomplete="off">
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label">Purchase Account</label>
|
|
<input type="text" class="form-control account_search" id="product_account_purchase"
|
|
placeholder="Search account..." autocomplete="off">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-light" data-bs-dismiss="modal">Cancel</button>
|
|
<button type="button" class="btn btn-primary" onclick="save_product_account_mapping()">
|
|
<i class="ti ti-device-floppy me-1"></i>Save Accounts
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php require '../include_ending.php'; ?>
|
|
|
|
<script>
|
|
var all_accounts = [];
|
|
var all_formulas = [];
|
|
var all_products = [];
|
|
var item_index = 0;
|
|
|
|
var doc_labels = {
|
|
sales_invoice: 'Sales Invoice',
|
|
sales_credit_note: 'Sales Credit Note',
|
|
receipt: 'Receipt',
|
|
purchase_invoice: 'Purchase Invoice',
|
|
supplier_credit_note: 'Supplier Credit Note',
|
|
payment: 'Payment',
|
|
};
|
|
|
|
function account_display(account_code) {
|
|
var account = all_accounts.find(a => String(a.account_code) === String(account_code));
|
|
return account ? `${account.account_code} - ${account.account_name}` : (account_code || '');
|
|
}
|
|
|
|
function account_badge(account_code) {
|
|
var label = account_display(account_code);
|
|
return label ? escape_html(label) : '<span class="badge bg-warning text-dark">Not mapped</span>';
|
|
}
|
|
|
|
function product_status_badge(status) {
|
|
return String(status) === '1' ? '<span class="badge bg-success">Active</span>' : '<span class="badge bg-secondary">Inactive</span>';
|
|
}
|
|
|
|
function product_account_row(product) {
|
|
var product_name = product.product_name || product.name || '';
|
|
return `<tr>
|
|
<td class="py-3 fw-semibold">${escape_html(product_name)}</td>
|
|
<td class="py-3">${escape_html(product.sku || '')}</td>
|
|
<td class="py-3">${account_badge(product.sales_account_code)}</td>
|
|
<td class="py-3">${account_badge(product.purchase_account_code)}</td>
|
|
<td class="py-3">${product_status_badge(product.status)}</td>
|
|
<td class="py-3">
|
|
<a href="javascript:;" onclick="open_product_account_modal(${product.id || 0})"><i class="ti ti-pencil fs-5"></i></a>
|
|
</td>
|
|
</tr>`;
|
|
}
|
|
|
|
function set_product_account_modal_field(input_selector, hidden_selector, account_code) {
|
|
var label = account_display(account_code || '');
|
|
$(input_selector)
|
|
.val(label)
|
|
.attr('data-account-code', account_code || '')
|
|
.attr('secondary', label);
|
|
$(hidden_selector).val(account_code || '');
|
|
}
|
|
|
|
function open_product_account_modal(product_id) {
|
|
var product = all_products.find(function(row) {
|
|
return String(row.id) === String(product_id);
|
|
});
|
|
if (!product) return;
|
|
|
|
$('#product_account_product_id').val(product.id || '');
|
|
$('#product_account_modal_product').text((product.product_name || product.name || '') + ' / ' + (product.sku || ''));
|
|
set_product_account_modal_field('#product_account_sales', '#product_account_sales_code', product.sales_account_code || '');
|
|
set_product_account_modal_field('#product_account_purchase', '#product_account_purchase_code', product.purchase_account_code || '');
|
|
|
|
if (window.init_account_search_inputs) window.init_account_search_inputs('#product_account_modal', all_accounts);
|
|
$('#product_account_modal').modal('show');
|
|
}
|
|
|
|
function save_product_account_mapping() {
|
|
ajax_request({
|
|
url: '<?php echo $server_url?>accounting/api/engine/product_account_mapping.php',
|
|
autoPrepare: true,
|
|
checkRequired: 0,
|
|
action: 'save',
|
|
data: {
|
|
id: $('#product_account_product_id').val(),
|
|
sales_account_code: $('#product_account_sales_code').val(),
|
|
purchase_account_code: $('#product_account_purchase_code').val(),
|
|
},
|
|
onSuccess: function() {
|
|
$('#product_account_modal').modal('hide');
|
|
retrieve_products();
|
|
}
|
|
});
|
|
}
|
|
|
|
function show_account_tab(tab) {
|
|
$('#formula_form').addClass('d-none');
|
|
$('#formula_list_section').toggleClass('d-none', tab !== 'formulas');
|
|
$('#product_account_section').toggleClass('d-none', tab !== 'product_accounts');
|
|
$('#tab_formulas').toggleClass('active', tab === 'formulas');
|
|
$('#tab_product_accounts').toggleClass('active', tab === 'product_accounts');
|
|
if (tab === 'product_accounts') render_product_account_list();
|
|
}
|
|
|
|
function amount_options(selected) {
|
|
var keys = ['grand_total', 'total', 'tax', 'amount'];
|
|
var opts = '';
|
|
keys.forEach(function(key) {
|
|
opts += `<option value="${key}" ${selected === key ? 'selected' : ''}>${key}</option>`;
|
|
});
|
|
return opts;
|
|
}
|
|
|
|
function add_item_row(item) {
|
|
item = item || {};
|
|
var idx = item_index++;
|
|
var row = `<tr id="formula_item_${idx}">
|
|
<td>
|
|
<select class="form-select form-select-sm item_drcr">
|
|
<option value="D" ${item.drcr === 'D' ? 'selected' : ''}>Debit</option>
|
|
<option value="C" ${item.drcr === 'C' ? 'selected' : ''}>Credit</option>
|
|
</select>
|
|
</td>
|
|
<td>
|
|
<input type="text" class="form-control form-control-sm item_account account_search"
|
|
value="${escape_html(account_display(item.account_code || ''))}"
|
|
data-account-code-target=".item_account_code"
|
|
data-account-code="${escape_html(item.account_code || '')}"
|
|
${item.account_code ? `secondary="${escape_html(account_display(item.account_code))}"` : ''}
|
|
placeholder="Search account..." autocomplete="off">
|
|
<input type="hidden" class="item_account_code" value="${escape_html(item.account_code || '')}">
|
|
</td>
|
|
<td><select class="form-select form-select-sm item_amount">${amount_options(item.amount_key || 'grand_total')}</select></td>
|
|
<td><input type="text" class="form-control form-control-sm item_description" value="${escape_html(item.description || '')}" placeholder="Line memo"></td>
|
|
<td><a href="javascript:;" class="link-danger" onclick="remove_item(${idx})"><i class="ti ti-trash fs-5"></i></a></td>
|
|
</tr>`;
|
|
$('#item_tbody').append(row);
|
|
if (window.init_account_search_inputs) window.init_account_search_inputs(`#formula_item_${idx}`, all_accounts);
|
|
}
|
|
|
|
function remove_item(idx) {
|
|
$('#formula_item_' + idx).remove();
|
|
}
|
|
|
|
function show_formula_form() {
|
|
$('#formula_form').removeClass('d-none');
|
|
$('#formula_list_section').addClass('d-none');
|
|
$('#product_account_section').addClass('d-none');
|
|
$('#tab_formulas').addClass('active');
|
|
$('#tab_product_accounts').removeClass('active');
|
|
reset_formula_form();
|
|
}
|
|
|
|
function hide_formula_form() {
|
|
$('#formula_form').addClass('d-none');
|
|
show_account_tab('formulas');
|
|
}
|
|
|
|
function reset_formula_form() {
|
|
$('#id, #formula_name, #description').val('');
|
|
$('#document_type').val('sales_invoice');
|
|
$('#status').val('1');
|
|
$('#is_default').prop('checked', false);
|
|
$('#item_tbody').empty();
|
|
item_index = 0;
|
|
add_item_row({ drcr: 'D', amount_key: 'grand_total' });
|
|
add_item_row({ drcr: 'C', amount_key: 'grand_total' });
|
|
}
|
|
|
|
function collect_items() {
|
|
var items = [];
|
|
$('#item_tbody tr').each(function() {
|
|
var row = {
|
|
drcr: $(this).find('.item_drcr').val(),
|
|
account_code: $(this).find('.item_account_code').val() || $(this).find('.item_account').attr('data-account-code') || '',
|
|
amount_key: $(this).find('.item_amount').val(),
|
|
description: $(this).find('.item_description').val(),
|
|
};
|
|
if (row.account_code) items.push(row);
|
|
});
|
|
return items;
|
|
}
|
|
|
|
function retrieve_accounts() {
|
|
return ajax_request({
|
|
url: '<?php echo $server_url?>accounting/api/engine/account.php',
|
|
autoPrepare: true,
|
|
checkRequired: 0,
|
|
action: 'read',
|
|
onSuccess: function(res) {
|
|
all_accounts = res.output || [];
|
|
window.account_search_accounts = all_accounts;
|
|
if (window.init_account_search_inputs) window.init_account_search_inputs(document, all_accounts);
|
|
}
|
|
});
|
|
}
|
|
|
|
function retrieve_formulas() {
|
|
return ajax_request({
|
|
url: '<?php echo $server_url?>accounting/api/engine/account_formula.php',
|
|
autoPrepare: true,
|
|
checkRequired: 0,
|
|
action: 'read',
|
|
onSuccess: function(res) {
|
|
all_formulas = res.output || [];
|
|
render_formula_list();
|
|
}
|
|
});
|
|
}
|
|
|
|
function retrieve_products() {
|
|
return ajax_request({
|
|
url: '<?php echo $server_url?>inventory/api/engine/product.php',
|
|
autoPrepare: true,
|
|
checkRequired: 0,
|
|
queueLock: false,
|
|
noLoading: true,
|
|
action: 'read',
|
|
onSuccess: function(res) {
|
|
all_products = res.output || [];
|
|
render_product_account_list();
|
|
}
|
|
});
|
|
}
|
|
|
|
function render_formula_list() {
|
|
var keyword = $('#search_input').val().toLowerCase();
|
|
var type = $('#filter_document_type').val();
|
|
var rows = all_formulas.filter(function(f) {
|
|
var match_kw = !keyword ||
|
|
String(f.formula_name || '').toLowerCase().includes(keyword) ||
|
|
String(doc_labels[f.document_type] || f.document_type || '').toLowerCase().includes(keyword);
|
|
return match_kw && (!type || f.document_type === type);
|
|
});
|
|
|
|
var body = '';
|
|
if (!rows.length) {
|
|
$('table#formula_list tbody').html('<tr><td colspan="6" class="text-center py-5 text-muted">No account formulas found.</td></tr>');
|
|
$('table#formula_list tfoot').html('');
|
|
return;
|
|
}
|
|
|
|
alasql('CREATE TABLE IF NOT EXISTS account_formula_list');
|
|
alasql.tables.account_formula_list.data = rows;
|
|
$('table#formula_list tfoot').html(generate_pagination('formula_list', rows.length));
|
|
|
|
$.each(rows.slice(0, prop_limit), function(i, f) {
|
|
body += `<tr>
|
|
<td class="py-3 fw-semibold">${escape_html(f.formula_name || '')}</td>
|
|
<td class="py-3">${escape_html(doc_labels[f.document_type] || f.document_type || '')}</td>
|
|
<td class="py-3">${format_number(f.item_count || 0)}</td>
|
|
<td class="py-3">${String(f.is_default) === '1' ? '<span class="badge bg-primary">Default</span>' : '<span class="text-muted">—</span>'}</td>
|
|
<td class="py-3">${String(f.status) === '1' ? '<span class="badge bg-success">Active</span>' : '<span class="badge bg-secondary">Inactive</span>'}</td>
|
|
<td class="py-3">
|
|
<a href="javascript:;" onclick="edit_formula(${f.id})"><i class="ti ti-eye fs-5"></i></a>
|
|
<a href="javascript:;" class="link-danger ms-2" onclick="delete_formula(${f.id})"><i class="ti ti-trash fs-5"></i></a>
|
|
</td>
|
|
</tr>`;
|
|
});
|
|
$('table#formula_list tbody').html(body);
|
|
}
|
|
|
|
function change_page_formula_list(page_num) {
|
|
var offset = (page_num - 1) * prop_limit;
|
|
var rows = alasql(`SELECT * FROM account_formula_list LIMIT ${prop_limit} OFFSET ${offset}`);
|
|
var body = '';
|
|
$.each(rows, function(i, f) {
|
|
body += `<tr>
|
|
<td class="py-3 fw-semibold">${escape_html(f.formula_name || '')}</td>
|
|
<td class="py-3">${escape_html(doc_labels[f.document_type] || f.document_type || '')}</td>
|
|
<td class="py-3">${format_number(f.item_count || 0)}</td>
|
|
<td class="py-3">${String(f.is_default) === '1' ? '<span class="badge bg-primary">Default</span>' : '<span class="text-muted">—</span>'}</td>
|
|
<td class="py-3">${String(f.status) === '1' ? '<span class="badge bg-success">Active</span>' : '<span class="badge bg-secondary">Inactive</span>'}</td>
|
|
<td class="py-3">
|
|
<a href="javascript:;" onclick="edit_formula(${f.id})"><i class="ti ti-eye fs-5"></i></a>
|
|
<a href="javascript:;" class="link-danger ms-2" onclick="delete_formula(${f.id})"><i class="ti ti-trash fs-5"></i></a>
|
|
</td>
|
|
</tr>`;
|
|
});
|
|
$('table#formula_list tbody').html(body);
|
|
}
|
|
|
|
function render_product_account_list() {
|
|
var keyword = $('#product_account_search').val().toLowerCase();
|
|
var filter = $('#product_account_filter').val();
|
|
var rows = all_products.filter(function(product) {
|
|
var sales_account = account_display(product.sales_account_code);
|
|
var purchase_account = account_display(product.purchase_account_code);
|
|
var has_sales = !!product.sales_account_code;
|
|
var has_purchase = !!product.purchase_account_code;
|
|
var match_kw = !keyword ||
|
|
String(product.product_name || product.name || '').toLowerCase().includes(keyword) ||
|
|
String(product.sku || '').toLowerCase().includes(keyword) ||
|
|
String(sales_account || '').toLowerCase().includes(keyword) ||
|
|
String(purchase_account || '').toLowerCase().includes(keyword);
|
|
|
|
if (!match_kw) return false;
|
|
if (filter === 'missing') return !has_sales || !has_purchase;
|
|
if (filter === 'mapped') return has_sales && has_purchase;
|
|
return true;
|
|
});
|
|
|
|
if (!rows.length) {
|
|
$('table#product_account_list tbody').html('<tr><td colspan="6" class="text-center py-5 text-muted">No product account mappings found.</td></tr>');
|
|
$('table#product_account_list tfoot').html('');
|
|
return;
|
|
}
|
|
|
|
alasql('CREATE TABLE IF NOT EXISTS product_account_list');
|
|
alasql.tables.product_account_list.data = rows;
|
|
$('table#product_account_list tfoot').html(generate_pagination('product_account_list', rows.length));
|
|
|
|
var body = '';
|
|
$.each(rows.slice(0, prop_limit), function(i, product) {
|
|
body += product_account_row(product);
|
|
});
|
|
$('table#product_account_list tbody').html(body);
|
|
}
|
|
|
|
function change_page_product_account_list(page_num) {
|
|
var offset = (page_num - 1) * prop_limit;
|
|
var rows = alasql(`SELECT * FROM product_account_list LIMIT ${prop_limit} OFFSET ${offset}`);
|
|
var body = '';
|
|
$.each(rows, function(i, product) {
|
|
body += product_account_row(product);
|
|
});
|
|
$('table#product_account_list tbody').html(body);
|
|
}
|
|
|
|
function edit_formula(id) {
|
|
ajax_request({
|
|
url: '<?php echo $server_url?>accounting/api/engine/account_formula.php',
|
|
autoPrepare: true,
|
|
checkRequired: 0,
|
|
action: 'retrieve',
|
|
data: { id: id },
|
|
onSuccess: function(res) {
|
|
var f = res.output || {};
|
|
$('#formula_form').removeClass('d-none');
|
|
$('#formula_list_section').addClass('d-none');
|
|
$('#product_account_section').addClass('d-none');
|
|
$('#tab_formulas').addClass('active');
|
|
$('#tab_product_accounts').removeClass('active');
|
|
$('#id').val(f.id || '');
|
|
$('#formula_name').val(f.formula_name || '');
|
|
$('#document_type').val(f.document_type || 'sales_invoice');
|
|
$('#description').val(f.description || '');
|
|
$('#status').val(String(f.status || 1));
|
|
$('#is_default').prop('checked', String(f.is_default) === '1');
|
|
$('#item_tbody').empty();
|
|
item_index = 0;
|
|
$.each(f.items || [], function(i, item) { add_item_row(item); });
|
|
}
|
|
});
|
|
}
|
|
|
|
function save_formula() {
|
|
ajax_request({
|
|
url: '<?php echo $server_url?>accounting/api/engine/account_formula.php',
|
|
autoPrepare: true,
|
|
checkRequired: 0,
|
|
action: 'save',
|
|
data: {
|
|
id: $('#id').val(),
|
|
formula_name: $('#formula_name').val(),
|
|
document_type: $('#document_type').val(),
|
|
description: $('#description').val(),
|
|
is_default: $('#is_default').is(':checked') ? 1 : 0,
|
|
status: $('#status').val(),
|
|
items: JSON.stringify(collect_items()),
|
|
},
|
|
onSuccess: function() {
|
|
hide_formula_form();
|
|
retrieve_formulas();
|
|
}
|
|
});
|
|
}
|
|
|
|
function delete_formula(id) {
|
|
bootbox.confirm('Disable this account formula?', function(ok) {
|
|
if (!ok) return;
|
|
ajax_request({
|
|
url: '<?php echo $server_url?>accounting/api/engine/account_formula.php',
|
|
autoPrepare: true,
|
|
checkRequired: 0,
|
|
action: 'delete',
|
|
data: { id: id },
|
|
onSuccess: retrieve_formulas
|
|
});
|
|
});
|
|
}
|
|
|
|
$(function() {
|
|
retrieve_accounts().then(function() {
|
|
retrieve_formulas();
|
|
retrieve_products();
|
|
});
|
|
$('#search_input').on('input', render_formula_list);
|
|
$('#filter_document_type').on('change', render_formula_list);
|
|
$('#product_account_search').on('input', render_product_account_list);
|
|
$('#product_account_filter').on('change', render_product_account_list);
|
|
$('#product_account_sales').on('account:selected', function(e, account) {
|
|
$('#product_account_sales_code').val(account.account_code || '');
|
|
}).on('account:cleared', function() {
|
|
$('#product_account_sales_code').val('');
|
|
});
|
|
$('#product_account_purchase').on('account:selected', function(e, account) {
|
|
$('#product_account_purchase_code').val(account.account_code || '');
|
|
}).on('account:cleared', function() {
|
|
$('#product_account_purchase_code').val('');
|
|
});
|
|
});
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|