From: erickson <erickson@dcc99617-32d9-48b4-a31d-7c20da2025e4> Date: Mon, 19 Apr 2010 00:04:26 +0000 (+0000) Subject: Added a lineitem summary view to describe details about related X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=2ebc1307d751299b80490b2747cd6de6b02eebc9;p=evergreen%2Fmasslnc.git Added a lineitem summary view to describe details about related lineitem_detail and order data Added a generic lineitem view function to generate a canned HTML blob to represent a lineitem using the new summary view Reduced some fleshing in ML calls in anticipation of larger invoices Use new summary lineitem fetch/render code in invoice page git-svn-id: svn://svn.open-ils.org/ILS/trunk@16268 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index f847a20e1f..dc39053bc9 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -5432,6 +5432,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA <field reporter:label="Line Item Notes" name="lineitem_notes" oils_persist:virtual="true" reporter:datatype="link" /> <field reporter:label="Distribution Formulas" name="distribution_formulas" oils_persist:virtual="true" reporter:datatype="link" /> <field reporter:label="Envoice Enties" name="invoice_entries" oils_persist:virtual="true" reporter:datatype="link" /> + <field reporter:label="Order Summary" name="order_summary" oils_persist:virtual="true" reporter:datatype="link" /> </fields> <links> <link field="selector" reltype="has_a" key="id" map="" class="au"/> @@ -5448,6 +5449,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA <link field="distribution_formulas" reltype="has_many" key="lineitem" map="" class="acqdfa"/> <link field="claim_policy" reltype="has_a" key="id" map="" class="acqclp"/> <link field="invoice_entries" reltype="has_many" key="lineitem" map="" class="acqie"/> + <link field="order_summary" reltype="might_have" key="lineitem" map="" class="acqlisum"/> </links> <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1"> <retrieve permission="CREATE_PURCHASE_ORDER VIEW_PURCHASE_ORDER CREATE_PICKLIST VIEW_PICKLIST"> @@ -7180,6 +7182,74 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA </links> </class> + <class id="acqlisum" controller="open-ils.cstore" oils_obj:fieldmapper="acq::lineitem_summary" oils_persist:readonly="true" reporter:label="Lineitem Summary"> + <oils_persist:source_definition> + + SELECT + li.id AS lineitem, + ( + SELECT COUNT(lid.id) + FROM acq.lineitem_detail lid + WHERE lineitem = li.id + ) AS item_count, + ( + SELECT COUNT(lid.id) + FROM acq.lineitem_detail lid + WHERE recv_time IS NOT NULL AND lineitem = li.id + ) AS recv_count, + ( + SELECT COUNT(lid.id) + FROM acq.lineitem_detail lid + WHERE cancel_reason IS NOT NULL AND lineitem = li.id + ) AS cancel_count, + ( + SELECT COUNT(lid.id) + FROM acq.lineitem_detail lid + JOIN acq.fund_debit debit ON (lid.fund_debit = debit.id) + WHERE NOT debit.encumbrance AND lineitem = li.id + ) AS invoice_count, + ( + SELECT COUNT(DISTINCT(lid.id)) + FROM acq.lineitem_detail lid + JOIN acq.claim claim ON (claim.lineitem_detail = lid.id) + WHERE lineitem = li.id + ) AS claim_count, + ( + SELECT (COUNT(lid.id) * li.estimated_unit_price)::NUMERIC(8,2) + FROM acq.lineitem_detail lid + WHERE lid.cancel_reason IS NULL AND lineitem = li.id + ) AS estimated_amount, + ( + SELECT SUM(debit.amount)::NUMERIC(8,2) + FROM acq.lineitem_detail lid + JOIN acq.fund_debit debit ON (lid.fund_debit = debit.id) + WHERE debit.encumbrance AND lineitem = li.id + ) AS encumbrance_amount, + ( + SELECT SUM(debit.amount)::NUMERIC(8,2) + FROM acq.lineitem_detail lid + JOIN acq.fund_debit debit ON (lid.fund_debit = debit.id) + WHERE NOT debit.encumbrance AND lineitem = li.id + ) AS paid_amount + + FROM acq.lineitem AS li + </oils_persist:source_definition> + <fields oils_persist:primary="lineitem" oils_persist:sequence="acq.lineitem_id_seq"> + <field reporter:label="Lineitem" name="lineitem" reporter:datatype="link"/> + <field reporter:label="Item Count" name="item_count" reporter:datatype="int"/> + <field reporter:label="Receive Count" name="recv_count" reporter:datatype="int"/> + <field reporter:label="Cancel Count" name="cancel_count" reporter:datatype="int"/> + <field reporter:label="Invoice Count" name="invoice_count" reporter:datatype="int"/> + <field reporter:label="Claim Count" name="claim_count" reporter:datatype="int"/> + <field reporter:label="Estimated Amount" name="estimated_amount" reporter:datatype="money"/> + <field reporter:label="Encumbrance Amount" name="encumbrance_amount" reporter:datatype="money"/> + <field reporter:label="Paid Amount" name="paid_amount" reporter:datatype="money"/> + </fields> + <links> + <link field="lineitem" reltype="has_a" key="id" map="" class="jub"/> + </links> + </class> + <class id="iatc" controller="open-ils.reporter-store" oils_obj:fieldmapper="action::intersystem_transit_copy" oils_persist:readonly="true" reporter:core="true" reporter:label="Inter-system Copy Transit"> <oils_persist:source_definition> diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Acq/Financials.pm b/Open-ILS/src/perlmods/OpenILS/Application/Acq/Financials.pm index 22ce5021c7..bfff04b8c3 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Acq/Financials.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Acq/Financials.pm @@ -942,6 +942,9 @@ sub retrieve_purchase_order_impl { $po->lineitems($items); $po->lineitem_count(scalar(@$items)); + } elsif( $$options{flesh_lineitem_ids} ) { + $po->lineitems($e->search_acq_lineitem({purchase_order => $po_id}, {idlist => 1})); + } elsif( $$options{flesh_lineitem_count} ) { my $items = $e->search_acq_lineitem({purchase_order => $po_id}, {idlist=>1}); diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Acq/Invoice.pm b/Open-ILS/src/perlmods/OpenILS/Application/Acq/Invoice.pm index a6533259a1..f0f08e1668 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Acq/Invoice.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Acq/Invoice.pm @@ -257,19 +257,12 @@ sub fetch_invoice_impl { "flesh" => 6, "flesh_fields" => { "acqinv" => ["entries", "items"], - "acqie" => ["lineitem", "purchase_order"], "acqii" => ["fund_debit"], - "jub" => ["attributes", "lineitem_details"], - "acqlid" => ["fund_debit"] } } ]; - my $invoice = $e->retrieve_acq_invoice($args) or return $e->die_event; - return $invoice if $options->{no_flesh_misc} or $options->{keep_li_marc}; - - $_->lineitem->clear_marc for @{$invoice->entries}; - return $invoice; + return $e->retrieve_acq_invoice($args); } __PACKAGE__->register_method( diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Acq/Lineitem.pm b/Open-ILS/src/perlmods/OpenILS/Application/Acq/Lineitem.pm index ce22e235b1..28bf41e85c 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Acq/Lineitem.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Acq/Lineitem.pm @@ -92,70 +92,62 @@ sub retrieve_lineitem_impl { my ($e, $li_id, $options) = @_; $options ||= {}; - # XXX finer grained perms... - - my $flesh = {}; - if($$options{flesh_attrs} or $$options{flesh_notes}) { - $flesh = {flesh => 2, flesh_fields => {jub => []}}; - if($$options{flesh_notes}) { - push(@{$flesh->{flesh_fields}->{jub}}, 'lineitem_notes'); - $flesh->{flesh_fields}->{acqlin} = ['alert_text']; + my $flesh = { + flesh => 3, + flesh_fields => { + jub => ['purchase_order', 'picklist'], # needed for permission check + acqlid => [], + acqlin => [] } - if($$options{"flesh_cancel_reason"}) { - push @{$flesh->{flesh_fields}->{jub}}, "cancel_reason"; - } - push(@{$flesh->{flesh_fields}->{jub}}, 'attributes') if $$options{flesh_attrs}; - } + }; - my $li = $e->retrieve_acq_lineitem([$li_id, $flesh]) or return $e->die_event; + my $fields = $flesh->{flesh_fields}; + + push(@{$fields->{jub}}, 'attributes') if $$options{flesh_attrs}; + push(@{$fields->{jub}}, 'lineitem_notes') if $$options{flesh_notes}; + push(@{$fields->{acqlin}}, 'alert_text') if $$options{flesh_notes}; + push(@{$fields->{jub}}, 'order_summary') if $$options{flesh_order_summary}; + push(@{$fields->{acqlin}}, 'cancel_reason') if $$options{flesh_cancel_reason}; if($$options{flesh_li_details}) { - my $ops = { - flesh => 1, - flesh_fields => {acqlid => ["cancel_reason"]} #XXX cancel_reason? always? really? - }; - push(@{$ops->{flesh_fields}->{acqlid}}, 'fund') if $$options{flesh_fund}; - push(@{$ops->{flesh_fields}->{acqlid}}, 'fund_debit') if $$options{flesh_fund_debit}; - if (my $details = $e->search_acq_lineitem_detail([{lineitem => $li_id}, $ops])) { - $li->lineitem_details($details); - $li->item_count(scalar(@$details)); - } else { - $li->lineitem_count(0); - } - } else { - my $details = $e->search_acq_lineitem_detail({lineitem => $li_id}, {idlist=>1}); - $li->item_count(scalar(@$details)); + push(@{$fields->{jub}}, 'lineitem_details'); + push(@{$fields->{acqlid}}, 'fund') if $$options{flesh_fund}; + push(@{$fields->{acqlid}}, 'fund_debit') if $$options{flesh_fund_debit}; + push(@{$fields->{acqlid}}, 'cancel_reason') if $$options{flesh_cancel_reason}; } - if($li->purchase_order) { - my $purchase_order = - $e->retrieve_acq_purchase_order($li->purchase_order) - or return $e->event; - - if($purchase_order->owner != $e->requestor->id) { - return $e->event unless - $e->allowed('VIEW_PURCHASE_ORDER', undef, $purchase_order); - } - - $li->purchase_order($purchase_order) if $$options{flesh_po}; + if($$options{clear_marc}) { # avoid fetching marc blob + my @fields = grep { $_ ne 'marc' } Fieldmapper::acq::lineitem->new->real_fields; + $flesh->{select} = {jub => [@fields]}; + } - } elsif($li->picklist) { - my $picklist = $e->retrieve_acq_picklist($li->picklist) - or return $e->event; - - if($picklist->owner != $e->requestor->id) { - return $e->event unless - $e->allowed('VIEW_PICKLIST', undef, $picklist); - } + my $li = $e->retrieve_acq_lineitem([$li_id, $flesh]) or return $e->event; - $li->picklist($picklist) if $$options{flesh_pl}; + # collect the # of lids + if($$options{flesh_li_details}) { + $li->item_count(scalar(@{$li->lineitem_details})); + } else { + my $details = $e->search_acq_lineitem_detail({lineitem => $li_id}, {idlist=>1}); + $li->item_count(scalar(@$details)); } - $li->clear_marc if $$options{clear_marc}; + return $e->event unless ( + $li->purchase_order and + $e->allowed(['VIEW_PURCHASE_ORDER', 'CREATE_PURCHASE_ORDER'], + $li->purchase_order->ordering_agency, $li->purchase_order) + ) or ( + $li->picklist and !$li->purchase_order and # user doesn't have view_po perms + $e->allowed(['VIEW_PICKLIST', 'CREATE_PICKLIST'], + $li->picklist->org_unit, $li->picklist) + ); + $li->clear_purchase_order unless $$options{flesh_po}; + $li->clear_picklist unless $$options{flesh_pl}; return $li; } + + __PACKAGE__->register_method( method => 'delete_lineitem', api_name => 'open-ils.acq.lineitem.delete', diff --git a/Open-ILS/web/css/skin/default/acq.css b/Open-ILS/web/css/skin/default/acq.css index 62619d3dc2..92bf05c3d0 100644 --- a/Open-ILS/web/css/skin/default/acq.css +++ b/Open-ILS/web/css/skin/default/acq.css @@ -210,6 +210,9 @@ span[name="notes_alert_flag"] {color: #c00;font-weight: bold;font-size: 110%;mar .acq-invoice-paid-col {background : #E0E0E0; text-align: center;} .acq-invoice-center-col { text-align: center; } +.acq-lineitem-summary { font-weight: bold; } +.acq-lineitem-summary-extra { padding-left: 10px; } + #acq-unified-heading { margin-bottom: 10px; } #acq-unified-heading-actual { float: left; width: 50%; font-size: 120%; font-weight: bold; } #acq-unified-heading-controls { float: right; width: 50%; text-align: right; } diff --git a/Open-ILS/web/js/dojo/openils/acq/Lineitem.js b/Open-ILS/web/js/dojo/openils/acq/Lineitem.js index d7d3958f21..6288d8b518 100644 --- a/Open-ILS/web/js/dojo/openils/acq/Lineitem.js +++ b/Open-ILS/web/js/dojo/openils/acq/Lineitem.js @@ -17,15 +17,16 @@ if(!dojo._hasResource['openils.acq.Lineitem']) { dojo._hasResource['openils.acq.Lineitem'] = true; dojo.provide('openils.acq.Lineitem'); - dojo.require('dojo.data.ItemFileWriteStore'); -dojo.require('dojox.grid.Grid'); -dojo.require('dojox.grid.compat._data.model'); dojo.require('fieldmapper.dojoData'); dojo.require('openils.User'); dojo.require('openils.Event'); dojo.require('openils.Util'); +dojo.requireLocalization('openils.acq', 'acq'); +var localeStrings = dojo.i18n.getLocalization('openils.acq', 'acq'); + + /** Declare the Lineitem class with dojo */ dojo.declare('openils.acq.Lineitem', null, { /* add instance methods here if necessary */ @@ -103,6 +104,71 @@ dojo.declare('openils.acq.Lineitem', null, { }, }); +openils.acq.Lineitem.identDisplayFields = ['isbn', 'upc', 'issn']; +openils.acq.Lineitem.fetchAndRender = function(liId, args, callback) { + + // below are the args needed for rendering the basic summary template + args = dojo.mixin(args || {}, { + clear_marc : true, + flesh_attrs : true, + flesh_po : true, + flesh_pl : true, + flesh_order_summary : true + }); + + fieldmapper.standardRequest( + ['open-ils.acq', 'open-ils.acq.lineitem.retrieve'], + { + params : [ openils.User.authtoken, liId, args ], + + oncomplete : function(r) { + var lineitem = openils.Util.readResponse(r); + if(!lineitem) return; + + var wrapper = new openils.acq.Lineitem({lineitem : lineitem}); + var type = 'lineitem_marc_attr_definition'; + + var idents = []; + dojo.forEach( + openils.acq.Lineitem.identDisplayFields, + function(ident) { + if(attr = wrapper.findAttr(ident, type)) + idents.push(attr) + } + ); + + var po = lineitem.purchase_order(); + var li = lineitem.picklist(); + + var displayString = dojo.string.substitute( + localeStrings.LINEITEM_SUMMARY, [ + wrapper.findAttr('title', type) || '', + wrapper.findAttr('author', type) || '', + idents.join(',') || '', + lineitem.order_summary().item_count() || '0', + lineitem.order_summary().recv_count() || '0', + Number(lineitem.estimated_unit_price()).toFixed(2) | '', + lineitem.order_summary().estimated_amount() || '0.00', + lineitem.order_summary().invoice_count() || '0', + lineitem.order_summary().claim_count() || '0', + lineitem.order_summary().cancel_count() || '0', + lineitem.id(), + oilsBasePath, + (po) ? po.id() : '', + (po) ? po.name() : '', + (li) ? li.id() : '', + (li) ? li.name() : '', + lineitem.order_summary().encumbrance_amount() || '0.00', + lineitem.order_summary().paid_amount() || '0.00', + ] + ); + + callback(lineitem, displayString); + } + } + ); +} + openils.acq.Lineitem.attrDefs = null; openils.acq.Lineitem.fetchAttrDefs = function(onload) { diff --git a/Open-ILS/web/js/dojo/openils/acq/nls/acq.js b/Open-ILS/web/js/dojo/openils/acq/nls/acq.js index dca18f6f7d..74f7d5216b 100644 --- a/Open-ILS/web/js/dojo/openils/acq/nls/acq.js +++ b/Open-ILS/web/js/dojo/openils/acq/nls/acq.js @@ -59,7 +59,13 @@ 'INVOICE_ITEM_DETAILS' : "${0} <br/> ${1} <br/> ${2}. <br/> Estimated Price: $${3}. <br/> Lineitem ID: ${4} <br/> PO: ${5} <br/> Order Date: ${6}", 'INVOICE_CONFIRM_ITEM_DELETE' : "Remove this $${0} '${1}' charge from the invoice?", 'INVOICE_CONFIRM_ENTRY_DETACH' : "Remove $${0} charge for item '${1}, ${2} [${3}] from the invoice?", - 'INVOICE_TITLE_DETAILS' : "<div class='acq-inoice-item-info'>${0}, by ${1} (${2})</div><div class='acq-inoice-item-extra-info'><a style='padding-right: 10px;' href='${9}/acq/po/view/${10}'>PO: ${11}</a>${3} Ordered, ${4} Received, ${7} Invoiced</div><div class='acq-inoice-item-extra-info'> Estimated Cost Per Item $${5} / Total Estimated Cost $${6}</div>", + 'LINEITEM_SUMMARY' : "<div class='acq-lineitem-summary'>${0}, by ${1} (${2})</div>" + + "<div class='acq-lineitem-summary-extra'>" + + "${3} Ordered, ${4} Received, ${7} Invoiced, ${8} Claimed, ${9} Cancelled</div>" + + "<div class='acq-lineitem-summary-extra'>Estimated $${6}, Encumbered $${16}, Paid $${17}</div>" + + "<div class='acq-lineitem-summary-extra'>" + + "<a style='padding-right: 10px;' href='${11}/acq/po/view/${12}'>PO: ${13}</a>" + + "<a style='padding-right: 10px;' href='${11}/acq/picklist/view/${14}'>SL: ${15}</a></div>", 'INVOICE_CONFIRM_PRORATE' : "Prorate charges?\n\nAny subsequent changes to the invoice that would affect prorated amounts should be resolved manually.", 'UNNAMED': "Unnamed", 'NO_FIND_INVOICE': "Could not find that invoice.\nNote that the Invoice # field is case-sensitive." diff --git a/Open-ILS/web/js/ui/default/acq/invoice/view.js b/Open-ILS/web/js/ui/default/acq/invoice/view.js index 69db886504..b80c207d93 100644 --- a/Open-ILS/web/js/ui/default/acq/invoice/view.js +++ b/Open-ILS/web/js/ui/default/acq/invoice/view.js @@ -10,6 +10,7 @@ dojo.require('openils.PermaCrud'); dojo.require('openils.widget.EditPane'); dojo.require('openils.widget.AutoFieldWidget'); dojo.require('openils.widget.ProgressDialog'); +dojo.require('openils.acq.Lineitem'); dojo.requireLocalization('openils.acq', 'acq'); var localeStrings = dojo.i18n.getLocalization('openils.acq', 'acq'); @@ -117,46 +118,24 @@ function renderInvoice() { function doAttachLi() { - fieldmapper.standardRequest( - ["open-ils.acq", "open-ils.acq.lineitem.retrieve"], { - async: true, - params: [openils.User.authtoken, attachLi, { - clear_marc : true, - flesh_attrs : true, - flesh_po : true, - flesh_li_details : true, - flesh_fund_debit : true - }], - oncomplete: function(r) { - lineitem = openils.Util.readResponse(r); - - if(cgi.param('create')) { - // render the invoice using some seed data from the Lineitem - var invoiceArgs = {provider : lineitem.provider(), shipper : lineitem.provider()}; - invoicePane = drawInvoicePane(dojo.byId('acq-view-invoice-div'), null, invoiceArgs); - } - - var entry = new fieldmapper.acqie(); - entry.id(virtualId--); - entry.isnew(true); - entry.lineitem(lineitem); - entry.purchase_order(lineitem.purchase_order()); - addInvoiceEntry(entry); - } - } - ); + //var invoiceArgs = {provider : lineitem.provider(), shipper : lineitem.provider()}; + if(cgi.param('create')) { + var invoiceArgs = {}; + invoicePane = drawInvoicePane(dojo.byId('acq-view-invoice-div'), null, invoiceArgs); + } + var entry = new fieldmapper.acqie(); + entry.id(virtualId--); + entry.isnew(true); + entry.lineitem(attachLi); + addInvoiceEntry(entry); } function doAttachPo() { + fieldmapper.standardRequest( ['open-ils.acq', 'open-ils.acq.purchase_order.retrieve'], { async: true, - params: [openils.User.authtoken, attachPo, { - flesh_lineitems : true, - clear_marc : true, - flesh_lineitem_details : true, - flesh_fund_debit : true - }], + params: [openils.User.authtoken, attachPo, {flesh_lineitem_ids : true}], oncomplete: function(r) { var po = openils.Util.readResponse(r); @@ -173,7 +152,6 @@ function doAttachPo() { entry.isnew(true); entry.lineitem(lineitem); entry.purchase_order(po); - lineitem.purchase_order(po); addInvoiceEntry(entry); } ); @@ -376,50 +354,21 @@ function addInvoiceEntry(entry) { entryTemplate = entryTbody.removeChild(dojo.byId('acq-invoice-entry-template')); } - if(dojo.query('[lineitem=' + entry.lineitem().id() +']', entryTbody)[0]) + if(dojo.query('[lineitem=' + entry.lineitem() +']', entryTbody)[0]) // Is it ever valid to have multiple entries for 1 lineitem in a single invoice? return; var row = entryTemplate.cloneNode(true); - row.setAttribute('lineitem', entry.lineitem().id()); - var lineitem = entry.lineitem(); - - var idents = []; - if(liMarcAttr(lineitem, 'isbn')) idents.push(liMarcAttr(lineitem, 'isbn')); - if(liMarcAttr(lineitem, 'upc')) idents.push(liMarcAttr(lineitem, 'upc')); - if(liMarcAttr(lineitem, 'issn')) idents.push(liMarcAttr(lineitem, 'issn')); - - var lids = lineitem.lineitem_details(); - var numOrdered = lids.length; - var numReceived = lids.filter(function(lid) { return (lid.recv_time() != null) }).length; - var numInvoiced = lids.filter(function(lid) { return !openils.Util.isTrue(lid.fund_debit().encumbrance()) }).length; - - var poName = ''; - var poId = ''; - var po = entry.purchase_order(); - if(po) { - poName = po.name(); - poId = po.id(); - } - - nodeByName('title_details', row).innerHTML = - dojo.string.substitute( - localeStrings.INVOICE_TITLE_DETAILS, [ - liMarcAttr(lineitem, 'title'), - liMarcAttr(lineitem, 'author'), - idents.join(','), - numOrdered, - numReceived, - Number(lineitem.estimated_unit_price()).toFixed(2), - (Number(lineitem.estimated_unit_price()) * numOrdered).toFixed(2), - numInvoiced, - lineitem.id(), - oilsBasePath, - poId, - poName - ] - ); - + row.setAttribute('lineitem', entry.lineitem()); + + openils.acq.Lineitem.fetchAndRender( + entry.lineitem(), {}, + function(li, html) { + entry.lineitem(li); + entry.purchase_order(li.purchase_order()); + nodeByName('title_details', row).innerHTML = html; + } + ); dojo.forEach( ['inv_item_count', 'phys_item_count', 'cost_billed', 'amount_paid'], @@ -579,11 +528,9 @@ function prorateInvoice(invoice) { } } ); - } - openils.Util.addOnLoad(init);