Item availability - part 4

Part four is now available on Github and forked on Stackblitz.

Item Availability Part 4

Additions are, excluding tinkering with previous parts:

This should now start to sound familiar.

ww-item-ledger

The item ledger request is again slightly different from previous requests:

export class WWItemLedgerRequest extends FormRequest {
    constructor(branch: string, item: string) {
        super();
        this.formName = 'P4111_W4111A';
        this.formServiceAction = 'R';
        this.maxPageSize = '1000';
        this.returnControlIDs = '17|67|21|39|1[6,7,8,9,10,11,12,13,155]';
        this.formInputs = [
            {
                id: '2',
                value: branch
            },
            {
                id: '5',
                value: item
            }
        ];
    }
}

We are now passing the branch and item as formInputs.

store update

We create new ledger app-state variable.

export interface ILedger {
  item: string;
  branch: string;
  transaction: Date;
  quantity: number;
}
export interface IAppState {
  items: IItem[];
  available: IItem[];
  quantities: IQuantity[];
  ledger: ILedger[];
}

A new action for the ledger and also an action to remove a card.

  export class RemoveAction implements Action {
    readonly type = ActionTypes.REMOVE;
    constructor(public item: string) { }
  }
  export class LedgerAction implements Action {
    readonly type = ActionTypes.LEDGER;
    constructor(public ledger: ILedger[]) { }
  }

And reducer for the ledger and remove actions.

    case ActionTypes.REMOVE:
      return {
        ...state, ...{
          available: state.available.filter(r => r.item !== action.item),
          quantities: state.quantities.filter(r => r.item !== action.item)
        }
      }
    case ActionTypes.LEDGER:
      return {
        ...state, ...{
          ledger: [...action.ledger]
        }
      };

e1/effects

We have two new effects. The first one, updateLedger$ is triggered by an update of the AvailableAction and then submits ww-item-ledger requests.
In other words, whenever the quantities app-state variable is updated, go and fetch the ledger.

    @Effect({ dispatch: false })
    updateLedger$ = this.actions$.ofType<AppActions.AvailableAction>(ActionTypes.AVAILABLE)
        .pipe(
            map(action => action.quantities),
            tap(qt => {
                const ledgerRq = new BatchformRequest();
                ledgerRq.formRequests = qt
                    .filter(r => r.branch !== 'TOTAL')
                    .map(r => new WWItemLedgerRequest(r.branch, r.item));
                this.batch.request = ledgerRq;
                this.e1.call(this.batch);
            })
        );
    @Effect()

The second effect maps the ww-item-ledger request to the ledger app-state variable.

    itemLedger$ = this.actions$.ofType<E1Actions.BatchformResponseAction>(E1ActionTypes.BATCHFORM_RESPONSE)
        .pipe(
            map(action => action.payload.batchformResponse),
            filter(bf => bf[`fs_0_${W4111A}`]),
            withLatestFrom(this.store),
            switchMap(([bf, store]) => {
                const ledger: ILedger[] = [];
                for (let i = 0; bf[`fs_${i}_${W4111A}`]; i++) {
                    const form: IWWItemLedgerForm = bf[`fs_${i}_${W4111A}`];
                    ledger.push(...form.data.gridData.rowset.map<ILedger>(r => {
                        return {
                            item: form.data.txtItemNumber_17.value,
                            branch: r.sBranchPlant_9.value,
                            transaction: new Date(parseInt(r.dtTransactionDate_8.internalValue)),
                            quantity: r.mnQuantity_10.internalValue
                        }
                    }));
                }
                const existing = ledger.map(r => r.item);
                ledger.push(...store.app.ledger.filter(r => !existing.includes(r.item)));
                return OfObservable(new AppActions.LedgerAction(ledger));
            })
        );

item-ledger.component

For now, the item-ledger component is just a placeholder. Instead of giving it its own page, we want to place it onto the item’s card.
For this we use Angular Material’s Tabs Component on the card’s content so the user can tab between ‘Summary’ and ‘Ledger’ modes.

The other addition to the card are the two buttons at bottom. The left one refreshes the data and the red bin removes it. The refresh function would benefit by being on a timer. Updated every 15 minutes for example, something to look at in a later tutorial.

But now I need a refresh course on D3 before getting stuck into charting the ledger.