diff --git a/solid-invoicing.js b/solid-invoicing.js index 5132a03c675c55996c6304416a922c90c6f1bf14..4b0f4f540c6f8e911865062df0b5cb271f45170e 100644 --- a/solid-invoicing.js +++ b/solid-invoicing.js @@ -42,6 +42,14 @@ export class SolidInvoicing extends SolidTemplateElement { if (customerDisplay.hasAttribute('no-render')) customerDisplay.removeAttribute('no-render'); if (freelancerDisplay.hasAttribute('no-render')) freelancerDisplay.removeAttribute('no-render'); } + if (e.detail.route === "edit-invoice") { + const editForm = this.querySelector('#edit-customer-invoice'); + editForm.addEventListener('populate', () => { + setTimeout(() => { + editForm.component.change(); + }, 200); // TODO : clean up this + }, { once: true }); + } }); this.addEventListener('click', (e) => { @@ -130,8 +138,36 @@ export class SolidInvoicing extends SolidTemplateElement { const invoiceSrc = e.target.closest('.invoice-details')?.dataset.src; if (!invoiceSrc) return; store.subscribeVirtualContainerTo(taskSrc, invoiceSrc); - } + } }); + + // Totals calculation + this.addEventListener('formChange', (e) => { + if (e.target.classList.contains('js-calculate-totals')) { + let htAmount = 0; + const form = e.target; + const batches = Array.from(form.querySelectorAll('widget-form-batches')); + + // BATCHES + for (const batch of batches) { + const tasksAmount = Array.from(batch.querySelectorAll('widget-form-tasks [name="htAmount"]')); + const total = tasksAmount.reduce((acc, task) => { + return acc + (task && task.value ? Number.parseFloat(task.value) : 0) + }, 0) + batch.querySelector('[name="batch-footer"] [name="htAmount"]').setAttribute('value', total.toFixed(2)); + htAmount += total; + } + + // TOTAL + const totalEl = form.querySelector('widget-form-total'); + totalEl.querySelector('[name="htAmount"]').setAttribute('value', htAmount.toFixed(2)); + const tvaRate = form.component.value.tvaRate || 0; + const tvaAmount = (tvaRate / 100) * htAmount; + totalEl.querySelector('[name="tvaRate"]').setAttribute('value', tvaRate); + totalEl.querySelector('[name="tvaAmount"]').setAttribute('value', tvaAmount.toFixed(2)); + totalEl.querySelector('[name="ttcAmount"]').setAttribute('value', (htAmount + tvaAmount).toFixed(2)); + } + }) } /** @@ -334,6 +370,32 @@ export class SolidInvoicing extends SolidTemplateElement { multiple-tasks required-title > </solid-form> + <div name="batch-footer"> + <div name="ht-total"> + <solid-display-value name="ht-label" value="${this.localize('label.ht_amount')}"></solid-display-value> + <widget-money name="htAmount" value="0"></widget-money> + </div> + </div> + </template> + </solid-widget> + + <solid-widget name="widget-form-total"> + <template> + <div name="invoice-totals"> + <div name="totals-header">${this.localize('value.totals_header')}</div> + <div name="ht-total"> + <solid-display-value name="ht-label" value="${this.localize('label.value_ht')}"></solid-display-value> + <widget-money name="htAmount" value="0"></widget-money> + </div> + <div name="tva-total"> + <widget-tva-rate name="tvaRate" value="0"></widget-tva-rate> + <widget-money name="tvaAmount" value="0"></widget-money> + </div> + <div name="ttc-total"> + <solid-display-value name="ttc-label" value="${this.localize('label.value_ttc')}"></solid-display-value> + <widget-money name="ttcAmount" value="0"></widget-money> + </div> + </div> </template> </solid-widget> @@ -492,13 +554,14 @@ export class SolidInvoicing extends SolidTemplateElement { <h3 class="text-color-heading">${this.localize('title.invoice_create')}</h3> <solid-form - class="new-customer-invoice-form segment full whitespace-normal" + class="new-customer-invoice-form segment full whitespace-normal js-calculate-totals" data-src="${dataSrc}" nested-field="customerInvoices" fields="first-line(title, identifier), second-line(state, invoicingDate), batches, - last-line(tvaRate, additionalText)" + last-line(tvaRate, additionalText), + total" label-title="${this.localize('label.invoice_title')}" label-identifier="${this.localize('label.invoice_identifier')}" @@ -513,6 +576,7 @@ export class SolidInvoicing extends SolidTemplateElement { widget-invoicingDate="solid-form-date-label" widget-tvaRate="solid-form-number-label" widget-additionalText="solid-form-placeholder-label-text" + widget-total="widget-form-total" enum-state="${this.localize('option.edited')} = edited, ${this.localize('option.pending')} = pending, ${this.localize('option.sent')} = sent, ${this.localize('option.late')} = late, ${this.localize('option.paid')} = paid" class-first-line="segment full sm-whitespace-normal" class-second-line="segment full sm-whitespace-normal" @@ -539,12 +603,14 @@ export class SolidInvoicing extends SolidTemplateElement { <h3>${this.localize('title.invoice_modify')}</h3> <solid-form + id="edit-customer-invoice" bind-resources - class="segment full whitespace-normal" + class="segment full whitespace-normal js-calculate-totals" fields="first-line(title, identifier), second-line(state, invoicingDate), batches, - last-line(tvaRate, additionalText)" + last-line(tvaRate, additionalText), + total" label-title="${this.localize('label.invoice_title')}" label-identifier="${this.localize('label.invoice_identifier')}" label-state="${this.localize('label.invoice_state')}" @@ -557,6 +623,7 @@ export class SolidInvoicing extends SolidTemplateElement { widget-invoicingDate="solid-form-date-label" widget-tvaRate="solid-form-number-label" widget-additionalText="solid-form-placeholder-label-text" + widget-total="widget-form-total" enum-state="${this.localize('option.edited')} = edited, ${this.localize('option.pending')} = pending, ${this.localize('option.sent')} = sent, ${this.localize('option.late')} = late, ${this.localize('option.paid')} = paid" class-first-line="segment full sm-whitespace-normal" class-second-line="segment full sm-whitespace-normal"