<field reporter:label="Code" name="code" reporter:selector="name" reporter:datatype="id"/>
<field reporter:label="Label" name="name" reporter:datatype="text" oils_persist:i18n="true"/>
<field reporter:label="Prorate?" name="prorate" reporter:datatype="bool"/>
+ <field reporter:label="Blanket?" name="blanket" reporter:datatype="bool"/>
</fields>
<links/>
<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
},
where => {'+acqpoi' => {purchase_order => $po_id}}
});
+
+ # debits for invoice items linked to "blanket" po_items are
+ # considered part of the PO. We are not duplicating debits
+ # here with po_item debits, because blanket po_item debits
+ # plus related invoice_item debits are cumulitive.
+ my $inv_data = $e->json_query({
+ select => {
+ acqii => [
+ 'amount_paid',
+ {column => 'id', alias => 'item_id'}
+ ],
+ aiit => ['blanket'],
+ acqfdeb => [
+ 'encumbrance',
+ {column => 'amount', alias => 'debit_amount'}
+ ]
+ },
+ from => {
+ acqii => {
+ acqfdeb => {
+ type => 'left',
+ fkey => 'fund_debit',
+ field => 'id'
+ },
+ aiit => {}
+ }
+ },
+ where => {
+ '+acqii' => {purchase_order => $po_id},
+ '+aiit' => {blanket => 't'}
+ }
+ });
# sum amounts debited (for activated PO's) and amounts estimated
# (for pending PO's) for all lineitem_details and po_items.
my ($enc, $spent, $estimated) = (0, 0, 0);
- for my $deb (@$li_data, @$item_data) {
+ for my $deb (@$li_data, @$item_data, @$inv_data) {
if (defined $deb->{debit_amount}) { # could be $0
# we have a debit, treat it as authoritative.
# us the total esimated amount.
$estimated += (
- $deb->{estimated_unit_price} || $deb->{estimated_cost} || 0
+ $deb->{estimated_unit_price} ||
+ $deb->{estimated_cost} ||
+ $deb->{amount_paid} || 0
);
}
}
if ($items) {
for my $item (@$items) {
$item->invoice($invoice->id);
+
+ # future: cache item types
+ my $item_type = $e->retrieve_acq_invoice_item_type(
+ $item->inv_item_type) or return $e->die_event;
if ($item->isnew) {
$e->create_acq_invoice_item($item) or return $e->die_event;
- # future: cache item types
- my $item_type = $e->retrieve_acq_invoice_item_type(
- $item->inv_item_type) or return $e->die_event;
# This following complex conditional statement effecively means:
# 1) Items with item_types that are prorate are handled
or return $e->die_event;
$debit = $e->retrieve_acq_fund_debit($po_item->fund_debit)
or return $e->die_event;
- } else {
+
+ if ($U->is_true($item_type->blanket)) {
+ # Each payment toward a blanket charge results
+ # in a new debit to track the payment and
+ # decreasing the (encumbered) amount on the
+ # origin po-item debit by the amount paid.
+
+ $debit->amount($debit->amount - $item->amount_paid);
+ $e->update_acq_fund_debit($debit) or return $e->die_event;
+ $debit = undef;
+ }
+ }
+
+ if (!$debit) {
$debit = Fieldmapper::acq::fund_debit->new;
$debit->isnew(1);
}
my $debit = $e->retrieve_acq_fund_debit($item->fund_debit);
$debit->encumbrance('t');
$e->update_acq_fund_debit($debit) or return $e->die_event;
+
} elsif ($item->fund_debit) {
- $e->delete_acq_fund_debit($e->retrieve_acq_fund_debit($item->fund_debit))
- or return $e->die_event;
+
+ my $inv_debit = $e->retrieve_acq_fund_debit($item->fund_debit);
+
+ if ($U->is_true($item_type->blanket)) {
+ # deleting a payment against a blanket charge means
+ # we have to re-encumber the paid amount by adding
+ # it back to the debit linked to the source po_item.
+
+ my $po_debit = $e->retrieve_acq_fund_debit($item->po_item->fund_debit);
+ $po_debit->amount($po_debit->amount + $inv_debit->amount);
+
+ $e->update_acq_fund_debit($po_debit)
+ or return $e->die_event;
+ }
+
+ $e->delete_acq_fund_debit($inv_debit) or return $e->die_event;
}
+
} elsif ($item->ischanged) {
my $debit;
return $e->die_event;
}
+ if ($U->is_true($item_type->blanket)) {
+ # modifying a payment against a blanket charge means
+ # also modifying the amount encumbered on the source
+ # debit from the blanket po_item to keep things balanced.
+
+ my $po_debit = $e->retrieve_acq_fund_debit(
+ $item->po_item->fund_debit);
+ my $delta = $debit->amount - $item->amount_paid;
+ $po_debit->amount($po_debit->amount + $delta);
+
+ $e->update_acq_fund_debit($po_debit)
+ or return $e->die_event;
+ }
+
+
$debit->amount($item->amount_paid);
$debit->fund($item->fund);
CREATE TABLE acq.invoice_item_type (
code TEXT PRIMARY KEY,
name TEXT NOT NULL, -- i18n-ize
- prorate BOOL NOT NULL DEFAULT FALSE
+ prorate BOOL NOT NULL DEFAULT FALSE,
+ blanket BOOL NOT NULL DEFAULT FALSE,
+ CONSTRAINT aiit_not_blanket_and_prorate
+ CHECK (blanket IS FALSE OR prorate IS FALSE)
);
CREATE TABLE acq.po_item (
INSERT INTO acq.invoice_item_type (code,name) VALUES ('HND',oils_i18n_gettext('HND', 'Handling Charge', 'aiit', 'name'));
INSERT INTO acq.invoice_item_type (code,name) VALUES ('ITM',oils_i18n_gettext('ITM', 'Non-library Item', 'aiit', 'name'));
INSERT INTO acq.invoice_item_type (code,name) VALUES ('SUB',oils_i18n_gettext('SUB', 'Serial Subscription', 'aiit', 'name'));
+INSERT INTO acq.invoice_item_type (code, blanket, name) VALUES (
+ 'BLA', TRUE, oils_i18n_gettext('BLA', 'Blanket Order', 'aiit', 'name'));
+
INSERT INTO acq.invoice_method (code,name) VALUES ('EDI',oils_i18n_gettext('EDI', 'EDI', 'acqim', 'name'));
INSERT INTO acq.invoice_method (code,name) VALUES ('PPR',oils_i18n_gettext('PPR', 'Paper', 'acqit', 'name'));
--- /dev/null
+BEGIN;
+
+--SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+
+ALTER TABLE acq.invoice_item_type
+ ADD COLUMN blanket BOOLEAN NOT NULL DEFAULT FALSE,
+ ADD CONSTRAINT aiit_not_blanket_and_prorate
+ CHECK (blanket IS FALSE OR prorate IS FALSE);
+
+COMMIT;
--- /dev/null
+BEGIN;
+
+--SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+
+INSERT INTO acq.invoice_item_type (code, blanket, name) VALUES (
+ 'BLA', TRUE, oils_i18n_gettext('BLA', 'Blanket Order', 'aiit', 'name'));
+
+COMMIT;