Acq: Add PO notes interface and checkbox for vendor_public flag on any note
authorsenator <senator@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Thu, 11 Mar 2010 22:13:58 +0000 (22:13 +0000)
committersenator <senator@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Thu, 11 Mar 2010 22:13:58 +0000 (22:13 +0000)
git-svn-id: svn://svn.open-ils.org/ILS/trunk@15811 dcc99617-32d9-48b4-a31d-7c20da2025e4

Open-ILS/src/perlmods/OpenILS/Application/Acq/Financials.pm
Open-ILS/src/perlmods/OpenILS/Application/Acq/Order.pm
Open-ILS/web/css/skin/default/acq.css
Open-ILS/web/js/dojo/openils/acq/nls/acq.js
Open-ILS/web/js/ui/default/acq/common/li_table.js
Open-ILS/web/js/ui/default/acq/po/view_po.js
Open-ILS/web/templates/default/acq/common/li_table.tt2
Open-ILS/web/templates/default/acq/common/notes.tt2 [new file with mode: 0644]
Open-ILS/web/templates/default/acq/po/view.tt2

index 447ee4a..0648454 100644 (file)
@@ -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}) {
 
index 3a25988..77caccb 100644 (file)
@@ -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;
index e3d1872..10e75d2 100644 (file)
@@ -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;}
+
index 31d1cdb..7567496 100644 (file)
@@ -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"
 }
index 50d2c1c..1195aca 100644 (file)
@@ -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);
index 48426a6..d96d0e2 100644 (file)
@@ -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;
         }
     });
index 7383870..927b127 100644 (file)
     </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'>&#x2196; 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 &nbsp;&nbsp;</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 (file)
index 0000000..399e7d3
--- /dev/null
@@ -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">&#x2196; 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 &nbsp;&nbsp;</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>
index 7b04973..b301002 100644 (file)
                 <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 %]