<button class="btn btn-outline-secondary"
(click)="findContainer()" i18n>Submit</button>
</div>
+ <div class="form-check form-check-inline ml-2">
+ <input class="form-check-input" type="checkbox"
+ id="receive-on-scan" [(ngModel)]="receiveOnScan"/>
+ <label class="form-check-label" for="receive-on-scan">Receive on Scan</label>
+ </div>
</div>
</div>
</div>
<div class="flex-1"
[ngClass]="{
'text-success': liWantedCount(li.id) == li.lids.length,
- 'text-danger': liWantedCount(li.id) < li.lids.length
+ 'text-danger': liWantedCount(li.id) > li.lids.length
}">
{{li.lids.length}}</div>
</li>
barcode = '';
receiving = false;
dryRun = true;
+ receiveOnScan = false;
// Technically possible for one container code to match across providers.
container: IdlObject;
{container_code: this.barcode},
{flesh: 1, flesh_fields: {acqsn: ['entries', 'provider']}}
).subscribe(
- sn => this.containers.push(sn),
- _ => {},
- () => {
-
- // TODO handle multiple containers w/ same code
- if (this.containers.length === 1) {
- this.container = this.containers[0];
- this.loadContainer();
- }
-
- const node = document.getElementById('barcode-search-input');
- (node as HTMLInputElement).select();
- }
+ sn => this.containers.push(sn),
+ _ => {},
+ () => {
+
+ // TODO handle multiple containers w/ same code
+ if (this.containers.length === 1) {
+ this.container = this.containers[0];
+ this.loadContainer();
+ if (this.receiveOnScan) {
+ this.receiveAllItems();
+ }
+ }
+
+ const node = document.getElementById('barcode-search-input');
+ (node as HTMLInputElement).select();
+ }
);
}
_ => {},
() => {
this.entries = entries;
- this.grid.reload();
+
+ if (this.grid) {
+ // Hidden of receiveOnScan
+ this.grid.reload();
+ }
}
);
}
.subscribe(
resp => {
this.progress.update({value: resp.progress});
- console.debug("ASN Receive returned", resp);
+ console.debug('ASN Receive returned', resp);
this.receiveResponse = resp;
},
err => {},
() => {
- // this.receiving = false;
}
);
}
push(@{$resp->{lineitems}}, $li_resp);
- my $lid_ids = $e->search_acq_lineitem_detail(
- [{ lineitem => $entry->lineitem,
- recv_time => undef,
- cancel_reason => undef # TODO delayed?
- }, {
- limit => $entry->item_count,
- order_by => {acqlid => 'id'}
- }],
- {idlist => 1}
- );
+ # Include canceled items.
+ my $lids = $e->search_acq_lineitem_detail([{
+ lineitem => $entry->lineitem,
+ recv_time => undef
+ }, {
+ flesh => 1,
+ flesh_fields => {acqlid => ['cancel_reason']}
+ }]);
+
+ # Start by receiving un-canceled items.
+ # Then try "delayed" items if it comes to that.
+ # Apply sorting for consistency with dry-run.
+
+ my @active_lids = sort {$a->id cmp $b->id}
+ grep {!$_->cancel_reason} @$lids;
- if (scalar(@$lid_ids) < $entry->item_count) {
+ my @canceled_lids = sort {$a->id cmp $b->id}
+ grep { $_->cancel_reason && $U->is_true($_->cancel_reason->keep_debits)
+ } @$lids;
+
+ my @potential_lids = (@active_lids, @canceled_lids);
+
+ if (scalar(@potential_lids) < $entry->item_count) {
$logger->warn(sprintf(
- "ASN $asn_id entry %d found %d receivable items, but wanted %d",
- $entry->id, scalar(@$lid_ids), $entry->item_count));
+ "ASN $asn_id entry %d found %d receivable items for lineitem %d, but wanted %d",
+ $entry->id, scalar(@potential_lids), $entry->lineitem, $entry->item_count
+ ));
}
- for my $li_id (@$lid_ids) {
- return $e->die_event unless receive_lineitem_detail($mgr, $li_id);
+ my $recv_count = 0;
+
+ for my $lid (@potential_lids) {
- my $lid = $e->retrieve_acq_lineitem_detail($li_id);
+ return $e->die_event unless receive_lineitem_detail($mgr, $lid->id);
+
+ # Get an updated copy to pick up the recv_time
+ $lid = $e->retrieve_acq_lineitem_detail($lid->id);
my $note = $lid->note ? $lid->note . "\n" : '';
$note .= "Received via shipment notification #$asn_id";
$e->update_acq_lineitem_detail($lid) or return $e->die_event;
- push(@{$li_resp->{lids}}, $li_id);
+ push(@{$li_resp->{lids}}, $lid->id);
$resp->{progress}++;
$client->respond($resp);
+
+ last if ++$recv_count >= $entry->item_count;
}
}