"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.zonePickingWorksheet = exports.zoneWorksheetOverview = void 0;
const typeorm_1 = require("typeorm");
const worksheet_base_1 = require("@things-factory/worksheet-base");
const warehouse_base_1 = require("@things-factory/warehouse-base");
const sales_base_1 = require("@things-factory/sales-base");
exports.zoneWorksheetOverview = {
    async zoneWorksheetOverview(_, { releaseGoods }, context) {
        const { domain, tx } = context.state;
        let data = await tx.query(`
      select 
        b.name as "company", 
        count(distinct oi.product_id) as "noOfSku", 
        count(distinct rg.name) as "noOfRo", 
        l.zone as "zone"
      from order_inventories oi 
      inner join release_goods rg on oi.release_good_id = rg.id 
      inner join inventories i on oi.inventory_id = i.id 
      inner join locations l on i.location_id = l.id 
      inner join products p on oi.product_id = p.id
      inner join bizplaces b on rg.bizplace_id = b.id 
      where rg.name = ANY($1)
        and rg.domain_id = $2
      group by b.name, l.zone
    `, [releaseGoods, domain.id]);
        let items = data.map(item => {
            return {
                company: item.company,
                noOfSku: parseInt(item.noOfSku, 10),
                noOfRo: parseInt(item.noOfRo, 10),
                zone: item.zone
            };
        });
        return { items };
    }
};
exports.zonePickingWorksheet = {
    async zonePickingWorksheet(_, { name, locationSortingRules, filter }, context) {
        const { domain } = context.state;
        let zoneWorksheet = {};
        //fetch worksheet
        let worksheet = await (0, typeorm_1.getRepository)(worksheet_base_1.Worksheet).findOne({
            where: {
                domain,
                name
            },
            relations: ['bizplace', 'assignee']
        });
        if (!worksheet) {
            throw new Error('unable to find worksheet');
        }
        zoneWorksheet.worksheet = worksheet;
        //fetch worksheet details
        zoneWorksheet.worksheetDetail = await (0, typeorm_1.getRepository)(worksheet_base_1.WorksheetDetail).find({
            where: { worksheet }
        });
        //fetch order inventories
        let qb = (0, typeorm_1.getRepository)(sales_base_1.OrderInventory)
            .createQueryBuilder('oi')
            .innerJoinAndSelect('oi.product', 'p', 'oi.product_id = p.id')
            .innerJoinAndSelect('oi.inventory', 'i', 'oi.inventory_id = i.id')
            .innerJoinAndSelect('i.location', 'l', 'i.location_id = l.id')
            .leftJoin('oi.releaseGood', 'rg', 'oi.release_good_id = rg.id')
            .leftJoinAndSelect('oi.productDetail', 'pd')
            .leftJoinAndSelect('pd.childProductDetail', 'cpd')
            .leftJoinAndSelect('pd.parentProductDetails', 'ppd')
            .where('ref_worksheet_id = :worksheetId', { worksheetId: worksheet.id });
        //get all oi to find inventory changes and determine if the worksheet is completable
        const orderInventories = await qb.getMany();
        //item assigned to obsolete inventories will not be displayed during picking
        if (filter) {
            qb.andWhere('rg.status != :orderStatus', { orderStatus: sales_base_1.ORDER_STATUS.OBSOLETE });
            qb.andWhere('oi.status != :terminateStatus', { terminateStatus: sales_base_1.ORDER_INVENTORY_STATUS.TERMINATED });
        }
        if (filter && filter == 'PICKING') {
            qb.andWhere('oi.status = :pickingStatus', { pickingStatus: sales_base_1.ORDER_INVENTORY_STATUS.PROCESSING });
        }
        if (filter && filter == 'PICKED') {
            qb.andWhere('oi.status = :pickedStatus', { pickedStatus: sales_base_1.ORDER_INVENTORY_STATUS.PICKED });
        }
        if ((locationSortingRules === null || locationSortingRules === void 0 ? void 0 : locationSortingRules.length) > 0) {
            locationSortingRules.forEach((rule) => {
                qb.addOrderBy(`l.${rule.name}`, rule.desc ? 'DESC' : 'ASC');
            });
        }
        //fetch inventory change for issues on all related inventories
        let invIds = [...new Set(orderInventories.map(oi => oi.inventoryId))];
        zoneWorksheet.inventoryChanges = await (0, typeorm_1.getRepository)(warehouse_base_1.InventoryChange).find({
            where: {
                inventory: (0, typeorm_1.In)(invIds),
                transactionType: (0, typeorm_1.In)(['MISSING', 'EXPIRED']),
                status: (0, typeorm_1.In)(['APPROVED', 'PENDING'])
            },
            relations: ['inventory', 'inventory.product']
        });
        //fetch ro related to the worksheet
        let roIds = [...new Set(orderInventories.map(item => item.releaseGoodId))];
        zoneWorksheet.releaseGood = await (0, typeorm_1.getRepository)(sales_base_1.ReleaseGood).find({
            where: { id: (0, typeorm_1.In)(roIds) }
        });
        //get all pickable items in the worksheet
        let items = await qb.getMany();
        //item with pending/approved inventory adjustment will not be displayed during picking
        if (filter) {
            zoneWorksheet.completable = isCompletable(orderInventories, zoneWorksheet.inventoryChanges);
            items = items.filter(oi => !zoneWorksheet.inventoryChanges.map(ic => ic.inventory.id).includes(oi.inventoryId));
        }
        //group oi based on inventory id
        const grouped = items === null || items === void 0 ? void 0 : items.reduce((group, oi) => {
            var _a;
            const inventoryId = (_a = oi.inventory) === null || _a === void 0 ? void 0 : _a.id;
            if (inventoryId) {
                if (!group[inventoryId]) {
                    group[inventoryId] = {
                        product: oi.product,
                        inventory: oi.inventory,
                        packingType: oi.packingType,
                        packingSize: oi.packingSize,
                        productDetail: oi.productDetail,
                        releaseQty: 0,
                        pickedQty: 0,
                        releaseUomValue: 0
                    };
                }
                //sum up the quantities and uom value
                group[inventoryId].releaseQty += oi.releaseQty || 0;
                group[inventoryId].pickedQty += oi.pickedQty || 0;
                group[inventoryId].releaseUomValue += oi.releaseUomValue || 0;
            }
            return group;
        }, {});
        //compute conversion string for each grouped item
        zoneWorksheet.groupedOrderInventories = Object.values(grouped).map((item) => (Object.assign(Object.assign({}, item), { conversion: (0, worksheet_base_1.computeConversionString)(item.releaseQty, item.productDetail) })));
        return zoneWorksheet;
    }
};
function isCompletable(oi, ic) {
    //find processing oi and check if there is any pending inventory adjustment
    let processingOi = oi.filter(item => item.status === sales_base_1.ORDER_INVENTORY_STATUS.PROCESSING);
    processingOi = processingOi.filter(item => !ic.filter(change => change.status === 'APPROVED').some(change => change.inventory.id === item.inventoryId));
    if (processingOi.length > 0 && oi.some(item => item.status === sales_base_1.ORDER_INVENTORY_STATUS.PICKED)) {
        return 'partial';
    }
    else if (processingOi.length > 0) {
        return 'false';
    }
    else {
        return 'true';
    }
}
//# sourceMappingURL=zone-worksheet.js.map