Bug 20253: Optionally use buyer's purchase order number from EDIFACT quote as basket name
This enhancement allows libraries to configure vendors to use the buyer's purchase order number (from RFF+ON segments) as the basket name instead of the EDIFACT filename, improving searchability and reference tracking. Backend Changes: - Added purchase_order_number() method to Koha::Edifact::Message to extract RFF+ON segments from message-level data (before first LIN segment) - Modified process_quote() in Koha::EDI to use purchase order number for basket naming when configured, with fallback to filename Frontend Changes: - Updated admin/edi_accounts.pl to handle po_is_basketname parameter - Added "Use purhase order numbers" option to EDI accounts template Test Plan: 1. Apply patches and run database update 2. Go to Administration > Acquisitions > EDI accounts 3. Create or edit a vendor EDI account 4. Verify "Use purchase order numbers" option appears 5. Enable "Use purchase order numbers" and save 6. Process an EDIFACT quote file that contains RFF+ON segments 7. Verify the created basket name uses the purchase order number instead of filename 8. Process a quote file without RFF+ON segments 9. Verify the basket name falls back to the filename 10. Test with "Use purchase order numbers" disabled 11. Verify basket names use filenames regardless of RFF+ON presence 12. Run tests: prove t/Edifact.t t/db_dependent/Koha/EDI.t The feature is optional and backward compatible - existing behavior is unchanged unless explicitly configured. Signed-off-by: Hannah Dunne-Howrie <hdunne-howrie@westminster.gov.uk> Sponsored-by: Westminster City Council <https://www.westminster.gov.uk/> Sponsored-by: Royal Borough of Kensington and Chelsea <https://www.rbkc.gov.uk/> Sponsored-by: OpenFifth <https://openfifth.co.uk/> Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com> Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This commit is contained in:
parent
168a5a9107
commit
4179211ce8
27
Koha/EDI.pm
27
Koha/EDI.pm
|
|
@ -649,11 +649,29 @@ sub process_quote {
|
|||
my $split_message;
|
||||
my @added_baskets; # if auto & multiple baskets need to order all
|
||||
|
||||
# Get vendor EDI account configuration
|
||||
my $v = $schema->resultset('VendorEdiAccount')->search(
|
||||
{
|
||||
vendor_id => $quote_message->vendor_id,
|
||||
}
|
||||
)->single;
|
||||
|
||||
if ( @{$messages} && $quote_message->vendor_id ) {
|
||||
|
||||
foreach my $msg ( @{$messages} ) {
|
||||
++$message_count;
|
||||
|
||||
# Determine basket name based on vendor configuration
|
||||
my $basket_name = $quote_message->filename;
|
||||
if ( $v && $v->po_is_basketname ) {
|
||||
my $purchase_order_number = $msg->purchase_order_number;
|
||||
if ($purchase_order_number) {
|
||||
$basket_name = $purchase_order_number;
|
||||
}
|
||||
}
|
||||
|
||||
my $basketno = NewBasket(
|
||||
$quote_message->vendor_id, 0, $quote_message->filename, q{},
|
||||
$quote_message->vendor_id, 0, $basket_name, q{},
|
||||
q{} . q{}
|
||||
);
|
||||
push @added_baskets, $basketno;
|
||||
|
|
@ -695,12 +713,7 @@ sub process_quote {
|
|||
$quote_message->status($status);
|
||||
$quote_message->update; # status and basketno link
|
||||
# Do we automatically generate orders for this vendor
|
||||
my $v = $schema->resultset('VendorEdiAccount')->search(
|
||||
{
|
||||
vendor_id => $quote_message->vendor_id,
|
||||
}
|
||||
)->single;
|
||||
if ( $v->auto_orders ) {
|
||||
if ( $v && $v->auto_orders ) {
|
||||
for my $i ( 0 .. $#added_baskets ) {
|
||||
my $basketno = $added_baskets[$i];
|
||||
|
||||
|
|
|
|||
|
|
@ -183,6 +183,22 @@ sub supplier_ean {
|
|||
|
||||
}
|
||||
|
||||
sub purchase_order_number {
|
||||
my $self = shift;
|
||||
foreach my $s ( @{ $self->{datasegs} } ) {
|
||||
if ( $s->tag eq 'LIN' ) {
|
||||
last;
|
||||
}
|
||||
if ( $s->tag eq 'RFF' ) {
|
||||
my $qualifier = $s->elem( 0, 0 );
|
||||
if ( $qualifier eq 'ON' ) {
|
||||
return $s->elem( 0, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sub lineitems {
|
||||
my $self = shift;
|
||||
if ( $self->{quotation_lines} ) {
|
||||
|
|
@ -280,6 +296,10 @@ Missing POD for buyer_ean.
|
|||
|
||||
Missing POD for supplier_ean.
|
||||
|
||||
=head2 purchase_order_number
|
||||
|
||||
Missing POD for purchase_order_number.
|
||||
|
||||
=head2 lineitems
|
||||
|
||||
Missing POD for lineitems.
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ if ( $op eq 'acct_form' ) {
|
|||
auto_orders => $input->param('auto_orders') ? 1 : 0,
|
||||
id_code_qualifier => scalar $input->param('id_code_qualifier'),
|
||||
plugin => scalar $input->param('plugin'),
|
||||
po_is_basketname => $input->param('po_is_basketname') ? 1 : 0,
|
||||
};
|
||||
|
||||
if ($id) {
|
||||
|
|
|
|||
|
|
@ -96,9 +96,10 @@
|
|||
<span>New account</span>
|
||||
[% END %]
|
||||
</h1>
|
||||
<fieldset class="rows">
|
||||
<legend class="sr-only">Account details</legend>
|
||||
|
||||
<!-- Basic Information -->
|
||||
<fieldset class="rows">
|
||||
<legend>Basic Information</legend>
|
||||
<ol>
|
||||
<li>
|
||||
<label for="vendor_id">Vendor: </label>
|
||||
|
|
@ -112,6 +113,10 @@
|
|||
[% END %]
|
||||
</select>
|
||||
</li>
|
||||
<li>
|
||||
<label for="description">Description: </label>
|
||||
<input type="text" name="description" id="description" size="20" value="[% account.description | html %]" />
|
||||
</li>
|
||||
[% IF plugins %]
|
||||
<li>
|
||||
<label for="plugin">Plugin: </label>
|
||||
|
|
@ -129,24 +134,6 @@
|
|||
[% ELSE %]
|
||||
<input type="hidden" name="plugin" value="" />
|
||||
[% END %]
|
||||
<li>
|
||||
<label for="description">Description: </label>
|
||||
<input type="text" name="description" id="description" size="20" value="[% account.description | html %]" />
|
||||
</li>
|
||||
<li>
|
||||
<label for="file_transport_id">File transport: </label>
|
||||
<select name="file_transport_id" id="file_transport_id">
|
||||
<option value="">Select a file transport configuration</option>
|
||||
[% FOREACH transport IN file_transports %]
|
||||
[% IF transport.file_transport_id == account.file_transport_id %]
|
||||
<option value="[% transport.file_transport_id | html %]" selected="selected">[% transport.name | html %] ([% transport.transport | upper | html %] - [% transport.host | html %])</option>
|
||||
[% ELSE %]
|
||||
<option value="[% transport.file_transport_id | html %]">[% transport.name | html %] ([% transport.transport | upper | html %] - [% transport.host | html %])</option>
|
||||
[% END %]
|
||||
[% END %]
|
||||
</select>
|
||||
<div class="hint"> Select a file transport configuration for this EDI account. File transports can be managed in <a href="/cgi-bin/koha/admin/file_transports.pl">Administration › File transports</a>. </div>
|
||||
</li>
|
||||
<li>
|
||||
<label for="id_code_qualifier">Qualifier:</label>
|
||||
<select name="id_code_qualifier" id="id_code_qualifier">
|
||||
|
|
@ -180,6 +167,34 @@
|
|||
[% END %]
|
||||
</select>
|
||||
</li>
|
||||
</ol>
|
||||
</fieldset>
|
||||
|
||||
<!-- Transport Settings -->
|
||||
<fieldset class="rows">
|
||||
<legend>Transport Settings</legend>
|
||||
<ol>
|
||||
<li>
|
||||
<label for="file_transport_id">File transport: </label>
|
||||
<select name="file_transport_id" id="file_transport_id">
|
||||
<option value="">Select a file transport configuration</option>
|
||||
[% FOREACH transport IN file_transports %]
|
||||
[% IF transport.file_transport_id == account.file_transport_id %]
|
||||
<option value="[% transport.file_transport_id | html %]" selected="selected">[% transport.name | html %] ([% transport.transport | upper | html %] - [% transport.host | html %])</option>
|
||||
[% ELSE %]
|
||||
<option value="[% transport.file_transport_id | html %]">[% transport.name | html %] ([% transport.transport | upper | html %] - [% transport.host | html %])</option>
|
||||
[% END %]
|
||||
[% END %]
|
||||
</select>
|
||||
<div class="hint"> Select a file transport configuration for this EDI account. File transports can be managed in <a href="/cgi-bin/koha/admin/file_transports.pl">Administration › File transports</a>. </div>
|
||||
</li>
|
||||
</ol>
|
||||
</fieldset>
|
||||
|
||||
<!-- Message Types -->
|
||||
<fieldset class="rows">
|
||||
<legend>Message Types</legend>
|
||||
<ol>
|
||||
<li>
|
||||
<label for="quotes_enabled">Quotes enabled: </label>
|
||||
[% IF account.quotes_enabled %]
|
||||
|
|
@ -212,6 +227,13 @@
|
|||
<input type="checkbox" name="responses_enabled" id="responses_enabled" value="1" />
|
||||
[% END %]
|
||||
</li>
|
||||
</ol>
|
||||
</fieldset>
|
||||
|
||||
<!-- Functional Switches -->
|
||||
<fieldset class="rows">
|
||||
<legend>Functional Switches</legend>
|
||||
<ol>
|
||||
<li>
|
||||
<label for="auto_orders">Automatic ordering: </label>
|
||||
[% IF account.auto_orders %]
|
||||
|
|
@ -221,6 +243,18 @@
|
|||
[% END %]
|
||||
<div class="hint"> With automatic ordering quotes generate orders without staff intervention. </div>
|
||||
</li>
|
||||
<li>
|
||||
<label for="po_is_basketname">Use purchase order numbers: </label>
|
||||
[% IF account.po_is_basketname %]
|
||||
<input type="checkbox" name="po_is_basketname" id="po_is_basketname" value="1" checked="checked" />
|
||||
[% ELSE %]
|
||||
<input type="checkbox" name="po_is_basketname" id="po_is_basketname" value="1" />
|
||||
[% END %]
|
||||
<div class="hint">
|
||||
When enabled, basket names are used as purchase order numbers. <br />For received QUOTE messages, we will use the RFF+ON field to populate the basket name. <br />For generated ORDER messages, we will use the
|
||||
basket name to populate the BGM segment.</div
|
||||
>
|
||||
</li>
|
||||
</ol>
|
||||
</fieldset>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue