From cc7549354f68e22377dce2fd6b299936f10a1c84 Mon Sep 17 00:00:00 2001 From: senator <senator@dcc99617-32d9-48b4-a31d-7c20da2025e4> Date: Thu, 11 Mar 2010 22:13:58 +0000 Subject: [PATCH] Acq: Add PO notes interface and checkbox for vendor_public flag on any note git-svn-id: svn://svn.open-ils.org/ILS/trunk@15811 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- .../perlmods/OpenILS/Application/Acq/Financials.pm | 6 +- .../src/perlmods/OpenILS/Application/Acq/Order.pm | 51 +++++++ Open-ILS/web/css/skin/default/acq.css | 18 ++- Open-ILS/web/js/dojo/openils/acq/nls/acq.js | 3 +- Open-ILS/web/js/ui/default/acq/common/li_table.js | 13 +- Open-ILS/web/js/ui/default/acq/po/view_po.js | 162 ++++++++++++++++++++- .../web/templates/default/acq/common/li_table.tt2 | 53 +------ .../web/templates/default/acq/common/notes.tt2 | 62 ++++++++ Open-ILS/web/templates/default/acq/po/view.tt2 | 9 ++ 9 files changed, 312 insertions(+), 65 deletions(-) create mode 100644 Open-ILS/web/templates/default/acq/common/notes.tt2 diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Acq/Financials.pm b/Open-ILS/src/perlmods/OpenILS/Application/Acq/Financials.pm index 447ee4a9c6..064845424d 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Acq/Financials.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Acq/Financials.pm @@ -894,7 +894,11 @@ sub retrieve_purchase_order_impl { my($e, $po_id, $options) = @_; $options ||= {}; - my $po = $e->retrieve_acq_purchase_order($po_id) or return $e->event; + my $po = $e->retrieve_acq_purchase_order( + $options->{"flesh_notes"} ? [ + $po_id, {"flesh" => 1, "flesh_fields" => {"acqpo" => ["notes"]}} + ] : $po_id + ) or return $e->event; if($$options{flesh_lineitems}) { diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm b/Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm index 3a259888f6..77caccb4d8 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm @@ -2364,4 +2364,55 @@ sub new_user_request { } +__PACKAGE__->register_method( + method => "po_note_CUD_batch", + api_name => "open-ils.acq.po_note.cud.batch", + stream => 1, + signature => { + desc => q/Manage purchase order notes/, + params => [ + {desc => "Authentication token", type => "string"}, + {desc => "List of po_notes to manage", type => "array"}, + ], + return => {desc => "Stream of successfully managed objects"} + } +); + +sub po_note_CUD_batch { + my ($self, $conn, $auth, $notes) = @_; + + my $e = new_editor("xact"=> 1, "authtoken" => $auth); + return $e->die_event unless $e->checkauth; + # XXX perms + + my $total = @$notes; + my $count = 0; + + foreach my $note (@$notes) { + + $note->editor($e->requestor->id); + $note->edit_time("now"); + + if ($note->isnew) { + $note->creator($e->requestor->id); + $note = $e->create_acq_po_note($note) or return $e->die_event; + } elsif ($note->isdeleted) { + $e->delete_acq_po_note($note) or return $e->die_event; + } elsif ($note->ischanged) { + $e->update_acq_po_note($note) or return $e->die_event; + } + + unless ($note->isdeleted) { + $note = $e->retrieve_acq_po_note($note->id) or + return $e->die_event; + } + + $conn->respond( + {"maximum" => $total, "progress" => ++$count, "note" => $note} + ); + } + + $e->commit and $conn->respond_complete or return $e->die_event; +} + 1; diff --git a/Open-ILS/web/css/skin/default/acq.css b/Open-ILS/web/css/skin/default/acq.css index e3d1872385..10e75d2ca8 100644 --- a/Open-ILS/web/css/skin/default/acq.css +++ b/Open-ILS/web/css/skin/default/acq.css @@ -139,13 +139,6 @@ label[for="attr_search_type_scalar"] { vertical-align: top; } #acq-lit-export-attr { margin-left: 10px; } .acq-lit-note-textarea { border-right: 2px solid #aaa; width:50%;} .acq-lit-note-textarea div { padding: 4px; font-weight: bold; } -#acq-lit-notes-tbody td {padding: 20px 10px 20px 10px; border-bottom:2px solid #aaa;} -#acq-lit-alert-value { height: 5em; width: 20em; } -.acq-lit-note-row { margin: 6px 0; } -span[name="alert_code"] {color: #c00;padding-right: 1em;font-weight: bold;} -span[name="notes_alert_flag"] {color: #c00;font-weight: bold;font-size: 110%;margin: 0 7px;} - -.acq-lit-li-menu-bar {width:99%; text-align:left; border:1px solid #aaa; margin:5px 0px 10px 0px;} .acq-lit-li-menu-left {text-align:left; width:300px;} .acq-lit-li-menu-right {text-align:left;} .acq-lit-distrib-form-use-count { color: #999; font-weight: bold; } @@ -154,4 +147,15 @@ span[name="notes_alert_flag"] {color: #c00;font-weight: bold;font-size: 110%;mar .acq-lit-distrib-applied-row th { border-bottom: 1px #999 solid;padding-bottom: 4px;} .acq-lit-table-spacer { height:20px; } .acq-lit-row td[name="selector"] { width:1.5em; font-weight:bold; color:blue; font-size:110%;} + +.acq-notes-menu-bar {width:99%; text-align:left; border:1px solid #aaa; margin:5px 0px 10px 0px;} +.acq-notes-note-row { margin: 6px 0; } +#acq-po-notes-tbody li { margin-bottom:10px; border:1px solid #aaa; -moz-border-radius: 5px 5px 5px 5px; } +#acq-po-notes-tbody td {padding: 20px 10px 20px 10px; border-bottom:2px solid #aaa;} #acq-lit-notes-tbody li { margin-bottom:10px; border:1px solid #aaa; -moz-border-radius: 5px 5px 5px 5px; } +#acq-lit-notes-tbody td {padding: 20px 10px 20px 10px; border-bottom:2px solid #aaa;} +#acq-lit-alert-value { height: 5em; width: 20em; } +span[name="vendor_public"] {color: #00c;padding-right: 1em;font-weight: bold;} +span[name="alert_code"] {color: #c00;padding-right: 1em;font-weight: bold;} +span[name="notes_alert_flag"] {color: #c00;font-weight: bold;font-size: 110%;margin: 0 7px;} + 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 31d1cdb3a2..7567496f53 100644 --- a/Open-ILS/web/js/dojo/openils/acq/nls/acq.js +++ b/Open-ILS/web/js/dojo/openils/acq/nls/acq.js @@ -26,5 +26,6 @@ 'DFA_TIP': "<strong>Applied by</strong>: ${0}<br /><strong>When</strong>: ${1}", 'ITS_YOU': "You", 'JUST_NOW': "Just now", - 'EXPLAIN_DFA_MGMT': "Remove record of this distribution formula usage?" + 'EXPLAIN_DFA_MGMT': "Remove record of this distribution formula usage?", + 'VENDOR_PUBLIC': "VENDOR PUBLIC" } diff --git a/Open-ILS/web/js/ui/default/acq/common/li_table.js b/Open-ILS/web/js/ui/default/acq/common/li_table.js index 50d2c1c21c..1195aca129 100644 --- a/Open-ILS/web/js/ui/default/acq/common/li_table.js +++ b/Open-ILS/web/js/ui/default/acq/common/li_table.js @@ -85,8 +85,6 @@ function AcqLiTable() { } - //dojo.byId('acq-lit-notes-new-button').onclick = function(){acqLitCreateLiNoteDialog.show();} - dojo.byId('acq-lit-select-toggle').onclick = function(){self.toggleSelect()}; dojo.byId('acq-lit-info-back-button').onclick = function(){self.show('list')}; dojo.byId('acq-lit-copies-back-button').onclick = function(){self.show('list')}; @@ -374,15 +372,20 @@ function AcqLiTable() { this.liNotesTbody.removeChild(this.liNotesTbody.childNodes[0]); this.show('notes'); - acqLitCreateLiNoteSubmit.onClick = function() { + acqLitCreateNoteSubmit.onClick = function() { var value = acqLitCreateNoteText.attr('value'); if(!value) return; var note = new fieldmapper.acqlin(); note.isnew(true); + note.vendor_public( + Boolean(acqLitCreateNoteVendorPublic.attr('checked')) + ); note.value(value); note.lineitem(li.id()); self.updateLiNotes(li, note); + acqLitCreateNoteVendorPublic.attr("checked", false); + acqLitCreateNoteText.attr("value", ""); } acqLitCreateAlertSubmit.onClick = function() { @@ -429,6 +432,10 @@ function AcqLiTable() { } } + if (note.vendor_public() == "t") + nodeByName("vendor_public", row).innerHTML = + localeStrings.VENDOR_PUBLIC; + nodeByName("delete", row).onclick = function() { note.isdeleted(true); self.liNotesTbody.removeChild(row); diff --git a/Open-ILS/web/js/ui/default/acq/po/view_po.js b/Open-ILS/web/js/ui/default/acq/po/view_po.js index 48426a6da8..d96d0e266f 100644 --- a/Open-ILS/web/js/ui/default/acq/po/view_po.js +++ b/Open-ILS/web/js/ui/default/acq/po/view_po.js @@ -5,6 +5,153 @@ dojo.require('openils.PermaCrud'); var PO = null; var liTable; +var poNoteTable; + +function AcqPoNoteTable() { + var self = this; + + this.notesTbody = dojo.byId("acq-po-notes-tbody"); + this.notesRow = this.notesTbody.removeChild(dojo.byId("acq-po-notes-row")); + + dojo.byId("acq-po-notes-back-button").onclick = function() { self.hide(); }; + dojo.byId("acq-po-view-notes").onclick = function() { self.show(); }; + + /* widgets' event properties are cased likeThis */ + acqPoCreateNoteSubmit.onClick = function() { + if (!acqPoCreateNoteText.attr("value")) return; + + /* prep new note */ + var note = new acqpon(); + note.vendor_public( + Boolean(acqPoCreateNoteVendorPublic.attr('checked')) + ); + note.value(acqPoCreateNoteText.attr("value")); + note.purchase_order(PO.id()); + note.isnew(true); + + /* save it */ + self.updatePoNotes(note); + + /* reset fields for next use */ + acqPoCreateNoteText.attr("value", ""); + acqPoCreateNoteVendorPublic.attr("checked", false); + }; + + this.drawPoNote = function(note) { + if (note.isdeleted()) + return; + + var row = dojo.clone(this.notesRow); + + nodeByName("value", row).innerHTML = note.value(); + + if (note.vendor_public() == "t") + nodeByName("vendor_public", row).innerHTML = + localeStrings.VENDOR_PUBLIC; + + nodeByName("delete", row).onclick = function() { + note.isdeleted(true); + self.notesTbody.removeChild(row); + self.updatePoNotes(); + }; + + if (note.edit_time()) { + nodeByName("edit_time", row).innerHTML = + dojo.date.locale.format( + dojo.date.stamp.fromISOString(note.edit_time()), + {"formatLength": "short"} + ); + } + + self.notesTbody.appendChild(row); + }; + + this.drawPoNotes = function() { + /* sort */ + PO.notes( + PO.notes().sort( + function(a, b) { + return (a.edit_time() < b.edit_time()) ? 1 : -1; + } + ) + ); + + /* remove old renderings of notes */ + dojo.empty(this.notesTbody); + + PO.notes().forEach(function(o) { self.drawPoNote(o); }); + }; + + this.updatePoNotesCount = function() { + dojo.byId("acq-po-view-notes").innerHTML = PO.notes().length; + }; + + this.updatePoNotes = function(newNote) { + var notes = newNote ? + [newNote] : + PO.notes().filter( + function(o) { + if (o.ischanged() || o.isnew() || o.isdeleted()) + return o; + } + ); + + if (notes.length < 1) + return; + + progressDialog.show(); + + fieldmapper.standardRequest( + ["open-ils.acq", "open-ils.acq.po_note.cud.batch"], { + "async": true, + "params": [openils.User.authtoken, notes], + "onresponse": function(r) { + var resp = openils.Util.readResponse(r); + if (resp) { + progressDialog.update(resp); + + if (!resp.note.isdeleted()) { + resp.note.isnew(false); + resp.note.ischanged(false); + PO.notes().push(resp.note); + } + } + }, + "oncomplete": function() { + if (!newNote) { + /* remove the old changed notes */ + var list = []; + PO.notes( + PO.notes().filter( + function(o) { + return (!( + o.ischanged() || o.isnew() || + o.isdeleted() + )); + } + ) + ); + } + + progressDialog.hide(); + self.updatePoNotesCount(); + self.drawPoNotes(); + } + } + ); + }; + + this.hide = function() { + openils.Util.hide("acq-po-notes-div"); + liTable.show("list"); + }; + + this.show = function() { + liTable.hide(); + self.drawPoNotes(); + openils.Util.show("acq-po-notes-div"); + }; +} function updatePoState(po_info) { var data = po_info[PO.id()]; @@ -22,6 +169,7 @@ function renderPo() { dojo.byId("acq-po-view-total-enc").innerHTML = PO.amount_encumbered(); dojo.byId("acq-po-view-total-spent").innerHTML = PO.amount_spent(); dojo.byId("acq-po-view-state").innerHTML = PO.state(); // TODO i18n + dojo.byId("acq-po-view-notes").innerHTML = PO.notes().length; if(PO.state() == "pending") { openils.Util.show("acq-po-activate"); @@ -30,16 +178,26 @@ function renderPo() { } } + function init() { + /* set up li table */ liTable = new AcqLiTable(); liTable.reset(); liTable.isPO = poId; liTable.poUpdateCallback = updatePoState; + /* set up po notes table */ + poNoteTable = new AcqPoNoteTable(); + + /* retrieve data and populate */ fieldmapper.standardRequest( ['open-ils.acq', 'open-ils.acq.purchase_order.retrieve'], { async: true, - params: [openils.User.authtoken, poId, {flesh_price_summary:true, flesh_lineitem_count:true}], + params: [openils.User.authtoken, poId, { + "flesh_price_summary": true, + "flesh_lineitem_count": true, + "flesh_notes": true + }], oncomplete: function(r) { PO = openils.Util.readResponse(r); /* save PO globally */ renderPo(); @@ -110,7 +268,7 @@ function updatePoName() { pcrud.update(PO, { oncomplete : function(r, cudResults) { var stat = cudResults[0]; - if(stat) + if(stat) dojo.byId('acq-po-view-name').innerHTML = value; } }); diff --git a/Open-ILS/web/templates/default/acq/common/li_table.tt2 b/Open-ILS/web/templates/default/acq/common/li_table.tt2 index 7383870e59..927b127011 100644 --- a/Open-ILS/web/templates/default/acq/common/li_table.tt2 +++ b/Open-ILS/web/templates/default/acq/common/li_table.tt2 @@ -130,57 +130,8 @@ </div> <!-- Lineitem notes table --> - <div id='acq-lit-notes-div' class='hidden'> - - <div class='acq-lit-li-menu-bar'> - <table style='width:100%'> - <tr> - <td style='text-align:left;'> - <div dojoType='dijit.form.Button' id='acq-lit-notes-back-button'>↖ Return</div> - </td> - <td style='text-align:right;'> - <div dojoType="dijit.form.DropDownButton"> - <span>New Note</span> - <div dojoType="dijit.TooltipDialog"> - <div class="acq-lit-note-row"> - <div jsId='acqLitCreateNoteText' dojoType='dijit.form.Textarea' style='height:5em; width:25em;' name='note'></div> - </div> - <button jsId='acqLitCreateLiNoteSubmit' dojoType='dijit.form.Button' type="submit">Create</button> - </div> - </div> - <div dojoType="dijit.form.DropDownButton"> - <span>New Alert</span> - <div dojoType="dijit.TooltipDialog"> - <div class="acq-lit-note-row"> - <label for="acq-lit-alert-alert-text">Choose alert code </label> - <input id="acq-lit-alert-alert-text" jsId="acqLitAlertAlertText" dojoType="dijit.form.FilteringSelect" labelAttr="code" searchAttr="code" required="true" /> - </div> - <div class="acq-lit-note-row"> - <label for="acq-lit-alert-value">Additional comments</label> - <div jsId="acqLitAlertNoteValue" id="acq-lit-alert-value" dojoType="dijit.form.Textarea" name="value"></div> - </div> - <button jsId="acqLitCreateAlertSubmit" dojoType="dijit.form.Button" type="submit">Create</button> - </div> - </div> - </td> - </tr> - </table> - </div> - - <ol id='acq-lit-notes-tbody'> - <li id='acq-lit-notes-row'> - <table style='width:100%;' class='oils-generic-table'> - <tr> - <td width='70%' align='left'><span name="alert_code"></span><span style='font-size:120%' name='value'></span></td> - <td align='right' style='padding-right:30px;'> - <span name='edit_time'></span> - <span style='padding-left:4px;'><a name='delete' href='javascript:void(0);' style='color:red;'>Delete</a></span> - </td> - </tr> - </div> - </li> - </ol> - </div> + [% note_table_for = "Lit" %] + [% INCLUDE "default/acq/common/notes.tt2" %] <!-- Copies table --> <div id='acq-lit-li-details' class='hidden'> diff --git a/Open-ILS/web/templates/default/acq/common/notes.tt2 b/Open-ILS/web/templates/default/acq/common/notes.tt2 new file mode 100644 index 0000000000..399e7d3522 --- /dev/null +++ b/Open-ILS/web/templates/default/acq/common/notes.tt2 @@ -0,0 +1,62 @@ +[% note_table_for_lc = note_table_for | lower %] + <div id="acq-[% note_table_for_lc %]-notes-div" class="hidden"> + <div class="acq-notes-menu-bar"> + <table style="width:100%"> + <tr> + <td style="text-align:left;"> + <div dojoType="dijit.form.Button" id="acq-[% note_table_for_lc %]-notes-back-button">↖ Return</div> + </td> + <td style="text-align:right;"> + <div dojoType="dijit.form.DropDownButton"> + <span>New Note</span> + <div dojoType="dijit.TooltipDialog"> + <div class="acq-notes-note-row"> + <div jsId="acq[% note_table_for %]CreateNoteText" dojoType="dijit.form.Textarea" style="height:5em; width:25em;" name="note"></div> + <div style="margin: 8px 0;"> + <div dojoType="dijit.form.CheckBox" jsId="acq[% note_table_for %]CreateNoteVendorPublic" name="vendor_public" id="acq-[% note_table_for_lc %]-create-note-vendor-public"></div><label for="acq-[% note_table_for_lc %]-create-note-vendor-public">Note is vendor-public</label> + </div> + </div> + <button jsId="acq[% note_table_for %]CreateNoteSubmit" dojoType="dijit.form.Button" type="submit">Create</button> + </div> + </div> +[% IF note_table_for == "Lit" %] + <div dojoType="dijit.form.DropDownButton"> + <span>New Alert</span> + <div dojoType="dijit.TooltipDialog"> + <div class="acq-notes-note-row"> + <label for="acq-lit-alert-alert-text">Choose alert code </label> + <input id="acq-lit-alert-alert-text" jsId="acqLitAlertAlertText" dojoType="dijit.form.FilteringSelect" labelAttr="code" searchAttr="code" required="true" /> + </div> + <div class="acq-notes-note-row"> + <label for="acq-lit-alert-value">Additional comments</label> + <div jsId="acqLitAlertNoteValue" id="acq-lit-alert-value" dojoType="dijit.form.Textarea" name="value"></div> + </div> + <button jsId="acqLitCreateAlertSubmit" dojoType="dijit.form.Button" type="submit">Create</button> + </div> + </div> +[% END %] + </td> + </tr> + </table> + </div> + + <ol id="acq-[% note_table_for_lc %]-notes-tbody"> + <li id="acq-[% note_table_for_lc %]-notes-row"> + <table style="width:100%;" class="oils-generic-table"> + <tr> + <td width="70%" align="left"> + <span name="vendor_public"></span> + <span name="alert_code"></span> + <span style="font-size:120%" name="value"></span> + </td> + <td align="right" style="padding-right:30px;"> + <span name="edit_time"></span> + <span style="padding-left:4px;"> + <a name="delete" href="javascript:void(0);" style="color:red;">Delete</a> + </span> + </td> + </tr> + </table> + </li> + </ol> + </div> diff --git a/Open-ILS/web/templates/default/acq/po/view.tt2 b/Open-ILS/web/templates/default/acq/po/view.tt2 index 7b04973bf0..b301002f03 100644 --- a/Open-ILS/web/templates/default/acq/po/view.tt2 +++ b/Open-ILS/web/templates/default/acq/po/view.tt2 @@ -13,6 +13,13 @@ <tr><td>Total Encumbered</td><td>$<span id='acq-po-view-total-enc'/></td></tr> <tr><td>Total Spent</td><td>$<span id='acq-po-view-total-spent'/></td></tr> <tr><td>Status</td><td><span id='acq-po-view-state'/></td></tr> + <tr> + <td>Notes</td> + <td> + <a href="javascript:void(0);" + id="acq-po-view-notes"></a> + </td> + </tr> <tr><td><a class='hidden' id='acq-po-activate' href='javascript:void(0);' onclick='activatePo()'>Activate Order</a></td></tr> <tr><td><a class="hidden" id="acq-po-split" href="javascript:void(0);" onclick="if (confirm(localeStrings.CONFIRM_SPLIT_PO)) splitPo();">Split Order by Lineitems</a></td></tr> </table> @@ -20,5 +27,7 @@ </div> <script type="text/javascript">var poId = '[% ctx.page_args.0 %]';</script> [% INCLUDE 'default/acq/common/li_table.tt2' %] + [% note_table_for = "Po" %] + [% INCLUDE "default/acq/common/notes.tt2" %] </div> [% END %] -- 2.11.0