unit cost
This commit is contained in:
1
migrations/add-unit-cost.sql
Normal file
1
migrations/add-unit-cost.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE invoice_items ADD COLUMN unit_cost character varying(50);
|
||||||
@@ -101,7 +101,11 @@ export function addItem(containerId, { item = null, type = 'invoice', laborRate
|
|||||||
<label class="block text-xs font-medium text-gray-700 mb-1">Rate</label>
|
<label class="block text-xs font-medium text-gray-700 mb-1">Rate</label>
|
||||||
<input type="text" data-item="${itemId}" data-field="rate" value="${item ? item.rate : ''}" class="${cssClass} w-full px-2 py-2 border border-gray-300 rounded-md text-sm">
|
<input type="text" data-item="${itemId}" data-field="rate" value="${item ? item.rate : ''}" class="${cssClass} w-full px-2 py-2 border border-gray-300 rounded-md text-sm">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-3">
|
<div class="col-span-1 cost-field" style="${(item && item.qbo_item_id && item.qbo_item_id != '9') ? 'display:none' : ''}">
|
||||||
|
<label class="block text-xs font-medium text-gray-700 mb-1">Cost</label>
|
||||||
|
<input type="text" data-item="${itemId}" data-field="unit_cost" value="${item && item.qbo_item_id == '9' ? (item.unit_cost || '') : ''}" class="${cssClass} w-full px-2 py-2 border border-gray-300 rounded-md text-sm">
|
||||||
|
</div>
|
||||||
|
<div class="col-span-2">
|
||||||
<label class="block text-xs font-medium text-gray-700 mb-1">Amount</label>
|
<label class="block text-xs font-medium text-gray-700 mb-1">Amount</label>
|
||||||
<input type="text" data-item="${itemId}" data-field="amount" value="${item ? item.amount : ''}" class="${amountClass} w-full px-2 py-2 border border-gray-300 rounded-md text-sm">
|
<input type="text" data-item="${itemId}" data-field="amount" value="${item ? item.amount : ''}" class="${amountClass} w-full px-2 py-2 border border-gray-300 rounded-md text-sm">
|
||||||
</div>
|
</div>
|
||||||
@@ -209,7 +213,6 @@ export function handleTypeChange(selectEl, prefix, itemId) {
|
|||||||
const rateInput = itemDiv.querySelector('[data-field="rate"]');
|
const rateInput = itemDiv.querySelector('[data-field="rate"]');
|
||||||
if (rateInput && (!rateInput.value || rateInput.value === '0')) {
|
if (rateInput && (!rateInput.value || rateInput.value === '0')) {
|
||||||
rateInput.value = laborRate;
|
rateInput.value = laborRate;
|
||||||
// Recalculate amount
|
|
||||||
const qtyInput = itemDiv.querySelector('[data-field="quantity"]');
|
const qtyInput = itemDiv.querySelector('[data-field="quantity"]');
|
||||||
const amountInput = itemDiv.querySelector('[data-field="amount"]');
|
const amountInput = itemDiv.querySelector('[data-field="amount"]');
|
||||||
if (qtyInput.value) {
|
if (qtyInput.value) {
|
||||||
@@ -219,6 +222,11 @@ export function handleTypeChange(selectEl, prefix, itemId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const costField = itemDiv.querySelector('.cost-field');
|
||||||
|
if (costField) {
|
||||||
|
costField.style.display = (selectEl.value === '9') ? '' : 'none';
|
||||||
|
}
|
||||||
|
|
||||||
updateItemPreview(itemDiv);
|
updateItemPreview(itemDiv);
|
||||||
onUpdate();
|
onUpdate();
|
||||||
}
|
}
|
||||||
@@ -236,11 +244,15 @@ export function getItems(containerId) {
|
|||||||
? descEditor.quillInstance.root.innerHTML
|
? descEditor.quillInstance.root.innerHTML
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
|
const qboItemId = div.querySelector('[data-field="qbo_item_id"]').value;
|
||||||
|
const unitCostInput = div.querySelector('[data-field="unit_cost"]');
|
||||||
|
|
||||||
items.push({
|
items.push({
|
||||||
quantity: div.querySelector('[data-field="quantity"]').value,
|
quantity: div.querySelector('[data-field="quantity"]').value,
|
||||||
qbo_item_id: div.querySelector('[data-field="qbo_item_id"]').value,
|
qbo_item_id: qboItemId,
|
||||||
description: descriptionHTML,
|
description: descriptionHTML,
|
||||||
rate: div.querySelector('[data-field="rate"]').value,
|
rate: div.querySelector('[data-field="rate"]').value,
|
||||||
|
unit_cost: (qboItemId === '9' && unitCostInput) ? unitCostInput.value : '',
|
||||||
amount: div.querySelector('[data-field="amount"]').value
|
amount: div.querySelector('[data-field="amount"]').value
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -88,10 +88,10 @@ CREATE TABLE public.invoice_items (
|
|||||||
amount character varying(50) NOT NULL,
|
amount character varying(50) NOT NULL,
|
||||||
item_order integer NOT NULL,
|
item_order integer NOT NULL,
|
||||||
created_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
|
created_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
|
||||||
qbo_item_id character varying(10) DEFAULT '9'::character varying
|
qbo_item_id character varying(10) DEFAULT '9'::character varying,
|
||||||
|
unit_cost character varying(50)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
ALTER TABLE public.invoice_items OWNER TO quoteuser;
|
ALTER TABLE public.invoice_items OWNER TO quoteuser;
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -192,8 +192,8 @@ router.post('/', async (req, res) => {
|
|||||||
|
|
||||||
for (let i = 0; i < items.length; i++) {
|
for (let i = 0; i < items.length; i++) {
|
||||||
await client.query(
|
await client.query(
|
||||||
'INSERT INTO invoice_items (invoice_id, quantity, description, rate, amount, item_order, qbo_item_id) VALUES ($1, $2, $3, $4, $5, $6, $7)',
|
'INSERT INTO invoice_items (invoice_id, quantity, description, rate, amount, item_order, qbo_item_id, unit_cost) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)',
|
||||||
[invoiceId, items[i].quantity, items[i].description, items[i].rate, items[i].amount, i, items[i].qbo_item_id || '9']
|
[invoiceId, items[i].quantity, items[i].description, items[i].rate, items[i].amount, i, items[i].qbo_item_id || '9', items[i].unit_cost || null]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,8 +333,8 @@ router.put('/:id', async (req, res) => {
|
|||||||
await client.query('DELETE FROM invoice_items WHERE invoice_id = $1', [id]);
|
await client.query('DELETE FROM invoice_items WHERE invoice_id = $1', [id]);
|
||||||
for (let i = 0; i < items.length; i++) {
|
for (let i = 0; i < items.length; i++) {
|
||||||
await client.query(
|
await client.query(
|
||||||
'INSERT INTO invoice_items (invoice_id, quantity, description, rate, amount, item_order, qbo_item_id) VALUES ($1, $2, $3, $4, $5, $6, $7)',
|
'INSERT INTO invoice_items (invoice_id, quantity, description, rate, amount, item_order, qbo_item_id, unit_cost) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)',
|
||||||
[id, items[i].quantity, items[i].description, items[i].rate, items[i].amount, i, items[i].qbo_item_id || '9']
|
[id, items[i].quantity, items[i].description, items[i].rate, items[i].amount, i, items[i].qbo_item_id || '9', items[i].unit_cost || null]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user