PageSourceSearch

https://estimatekit.com/assets/invoices-DXYLcQMo.js

js estimatekit.com collected 2026-10-04 03:35:28 UTC 3,170 bytes, 1 lines download raw bytes

1import{o,ag as T,al as N,S as A}from"./index-CbvCveKN.js";import{convertEstimateToJob as S,createFinalInvoiceForJob as F,friendly as d}from"./jobs-BslETRXA.js";const P={due_on_receipt:0,net_15:15,net_30:30,net_45:45};async function R(a){var p;const{data:e,error:n}=await o.from("estimates").select("id, client_name, approved_tier_id, materials_tax_rate, labor_tax_rate, tax_rate, status").eq("id",a).single();if(n||!e)throw new Error((n==null?void 0:n.message)||"Estimate not found");const[{data:i},{data:v},{data:m}]=await Promise.all([o.from("estimate_tiers").select("id, title, tier_number").eq("estimate_id",a).order("tier_number"),o.from("estimate_items").select("id, tier_id, item_name, item_description, category, quantity, unit_cost, sell_price, total, sort_order, materials(item_name)").eq("estimate_id",a).order("sort_order"),o.from("invoices").select("id").eq("estimate_id",a).neq("kind","deposit").limit(1).maybeSingle()]),s=i||[],y=v||[];let r=e.approved_tier_id;if(!r&&s.length===1&&(r=s[0].id),!r&&s.length>1)throw new Error("This estimate has several options and none was chosen. Approve it with an option first, or edit it down to one.");const _=y.filter(t=>r?t.tier_id===r:!0),b=s.length>1?((p=s.find(t=>t.id===r))==null?void 0:p.title)??null:null,g=_.map((t,q)=>{var h;const f=Number(t.sell_price??t.unit_cost)||0,w=Number(t.quantity)||1;return{item_name:t.item_name||((h=t.materials)==null?void 0:h.item_name)||"Item",item_description:t.item_description||null,category:t.category,quantity:w,unit_cost:f,total:Number(t.total)||f*w,sort_order:t.sort_order??q}}),x=Number(e.materials_tax_rate??e.tax_rate??0)||0,I=Number(e.labor_tax_rate??0)||0,c=T(N(_.map(t=>({...t,total:Number(t.total)}))),x,I),u=await A()??null,{data:l}=u?await o.from("user_preferences").select("invoice_payment_terms").eq("user_id",u).maybeSingle():{data:null},E=P[(l==null?void 0:l.invoice_payment_terms)||"net_30"]??30;return{estimateId:a,clientName:e.client_name,optionTitle:b,lineItems:g,subtotal:c.subtotal,taxAmount:c.totalTax,total:c.total,dueDays:E,existingInvoiceId:(m==null?void 0:m.id)??null}}async function M(a){const e=await R(a);if(e.existingInvoiceId)return{invoiceId:e.existingInvoiceId,existed:!0};if(e.lineItems.length===0)throw new Error("The approved option has no line items to invoice.");const{job_id:n}=await S(a);return{invoiceId:await F(n),existed:!1}}async function O(a,e){const{data:n,error:i}=await o.rpc("record_payment",{p_invoice_id:a,p_amount:e.amount,p_method:e.method,p_paid_at:e.paidAt,p_reference:e.reference||void 0,p_note:e.note||void 0});if(i)throw new Error(d(i.message));return n}async function j(a,e){if(!e.amount||e.amount<=0)throw new Error("Enter an amount above zero.");const{error:n}=await o.from("payments").update({amount:Math.round(e.amount*100)/100,method:e.method||"other",paid_at:e.paidAt,reference:e.reference||null,note:e.note||null}).eq("id",a);if(n)throw new Error(d(n.message))}async function k(a){const{error:e}=await o.from("payments").delete().eq("id",a);if(e)throw new Error(d(e.message))}export{M as createInvoiceFromEstimate,k as deletePayment,R as previewInvoiceFromEstimate,O as recordPayment,j as updatePayment};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.