"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.outboundOrderDetailsReport = void 0;
const auth_base_1 = require("@things-factory/auth-base");
const biz_base_1 = require("@things-factory/biz-base");
const utils_1 = require("../../../utils");
exports.outboundOrderDetailsReport = {
    async outboundOrderDetailsReport(_, params, context) {
        try {
            const { domain, user, tx } = context.state;
            let bizplaceFilter = { name: '', operator: '', value: '' };
            let userFilter = params.filters.find(data => data.name === 'user');
            let fromDate = params.filters.find(data => data.name === 'fromDate');
            let toDate = params.filters.find(data => data.name === 'toDate');
            let roNo = params.filters.find(data => data.name === 'roNo');
            let doNo = params.filters.find(data => data.name === 'doNo');
            let status = params.filters.find(data => data.name === 'status');
            let binLocation = params.filters.find(data => data.name === 'binLocation');
            let priorityDelivery = params.filters.find(data => data.name === 'priorityDelivery');
            let byPackingComplete = params.filters.find(data => data.name === 'byPackingComplete');
            if (userFilter) {
                const user = await tx.getRepository(auth_base_1.User).findOne({
                    where: { id: userFilter.value },
                    relations: ['bizplaces']
                });
                const bizplace = user.bizplaces[0];
                if (!bizplace)
                    throw 'Invalid input';
                bizplaceFilter = { name: 'bizplace', operator: 'eq', value: bizplace.id };
            }
            else {
                bizplaceFilter = params.filters.find(data => data.name === 'bizplace');
            }
            if (!bizplaceFilter || !fromDate || !toDate)
                throw 'Invalid input';
            const bizplace = await tx.getRepository(biz_base_1.Bizplace).findOne({
                id: bizplaceFilter.value
            });
            await (0, utils_1.rawProductsQuery)(tx, params, bizplace);
            // Apply filters using base table columns within the inner SELECT to avoid alias scoping issues
            // The first subquery joins delivery_orders as do2; the second does not. Split filters accordingly.
            let innerQueryFilters1 = '';
            let innerQueryFilters2 = '';
            const hasDoFilter = !!doNo;
            if (roNo) {
                innerQueryFilters1 = `${innerQueryFilters1} and rg.name like '%${roNo.value}%' `;
                innerQueryFilters2 = `${innerQueryFilters2} and rg.name like '%${roNo.value}%' `;
            }
            if (doNo) {
                innerQueryFilters1 = `${innerQueryFilters1} and do2.name like '%${doNo.value}%' `;
            }
            console.time('temp');
            await tx.query(`
        create temp table temp_outbound_order_report on commit drop as (
          select * from (
            select oi.id,
            oi.release_qty AS "release_qty", oi.picked_at, oi.picked_by, oi.packed_at, oi.packed_by, oi.loaded_at, oi.loaded_by, 
            oi.release_qty as "qty", oi.release_uom_value as "uom_value", oi.return_to_location_qty, oi.return_to_location_uom_value, oi.product_detail_id,
            l2.name as "picking_location",
            coalesce(do2.other_driver, td.name) as driver_name, 
            coalesce(do2.truck_no, tv.name, rg.truck_no) as vehicle_no,
            do2.name AS "delivery_order_no", do2.delivery_date::timestamp AS "delivery_order_delivery_date", do2."to", do2.contact_point_ref_id, do2.pallet_qty,
            coalesce(do2.delivery_date_time, do2.delivery_date::timestamp, ms.dispatched_at, null) as "dispatched_at",
            rg.bizplace_id, $5 AS "bizplace_name", $6 AS "bizplace_description", rg.priority_delivery as "priority_delivery",
            coalesce( concat(do2.delivery_address_1, do2.delivery_address_2, do2.delivery_address_3, do2.delivery_address_4, do2.delivery_address_5, do2.postal_code, do2.country), concat(rg.delivery_address_1, rg.delivery_address_2, rg.delivery_address_3, rg.delivery_address_4, rg.delivery_address_5, rg.postal_code, rg.country)) as delivery_address,
            so.container_no, so.container_size,
            rg.export_option, rg.name AS "ro_no", rg."type" as "ro_type", rg.ref_no AS "ref_no_1", rg.ref_no_2 AS "ref_no_2", rg.ref_no_3 AS "ref_no_3", rg.status as "ro_status", 
            u1.name as "order_created_by", rg.created_at AS "order_created_at",
            rg.accepted_at, u4.name as accepted_by, rg.checked_remark_by, rg.checked_remark_at, coalesce(do2.own_collection, rg.own_transport) AS own_transport,
            p.id as "product_id", p.sku as "product_sku", p.name AS "product_name", p.description AS "product_description", p.type as "product_type", oi.packing_type as "packing_type", oi.packing_size as "packing_size",
            i.uom, i.unit_cost,
            i.id as inventory_id, i.pallet_id, i.carton_id, i.batch_id, i.batch_id_ref, i.expiration_date, i.manufacture_date, 
            coalesce(ms.name,'') as manifest_no, coalesce(rg.manifested_at, ms.created_at) as manifested_at, coalesce(u6.name, u5.name) as manifested_by, l.name as picking_bin
            from release_goods rg
            left join users u1 on u1.id = rg.creator_id 
            inner join order_inventories oi on rg.id = oi.release_good_id
            left join locations l on l.id = oi.bin_location_id
            left join shipping_orders so on so.id = rg.shipping_order_id  
            left join users u4 on u4.id = rg.accepted_by_id 
            left join manifests ms on ms.id = rg.manifest_id
            left join users u5 on u5.id = ms.creator_id
            left join users u6 on u6.id = rg.manifested_by_id
            inner join inventories i on i.id = oi.inventory_id 
            inner join temp_products p on p.id = oi.product_id
            left join delivery_orders do2 on do2.id = oi.delivery_order_id 
            left join transport_drivers td ON td.id = do2.transport_driver_id 
            left join transport_vehicles tv on tv.id = do2.transport_vehicle_id
            left join locations l2 on l2.id = i.location_id
            where rg.bizplace_id = $2 and rg.domain_id = $1
            and rg.created_at >= $3 and rg.created_at <= $4
            and oi.status <> 'REPLACED'
            and oi.release_qty > 0
            ${status ? `and rg.status = '${status.value}' ` : ``}
            ${binLocation ? `and l.name ilike '${binLocation.value}' ` : ``}
            ${priorityDelivery ? `and rg.priority_delivery = ${priorityDelivery.value} ` : ``}
            ${innerQueryFilters1}
            and oi.release_qty > 0
          ) src 
          where 1=1
          ${hasDoFilter
                ? ''
                : `union all
          select * from (
            select op.id,
            op.release_qty AS "release_qty", NULL::timestamp, NULL, NULL::timestamp, NULL, NULL::timestamp, NULL,
            op.release_qty as "qty", op.release_uom_value as "uom_value", NULL:: double precision, null:: double precision, op.product_detail_id,
            NULL,
            NULL, NULL, 
            NULL, NULL::timestamp, NULL, null::uuid, null, 
            null::timestamp,
            rg.bizplace_id, $5 AS "bizplace_name", $6 AS "bizplace_description", rg.priority_delivery as "priority_delivery",
            NULL, so.container_no, so.container_size,
            rg.export_option, rg.name AS "ro_no", rg."type" as "ro_type", rg.ref_no AS "ref_no_1", rg.ref_no_2 AS "ref_no_2", rg.ref_no_3 AS "ref_no_3", rg.status as "ro_status", 
            u1.name as "order_created_by", rg.created_at AS "order_created_at",
            rg.accepted_at, u4.name as accepted_by, rg.checked_remark_by, rg.checked_remark_at, rg.own_transport AS own_transport,
            p.id as "product_id", p.sku as "product_sku", p.name AS "product_name", p.description AS "product_description", p.type as "product_type", op.packing_type as "packing_type", op.packing_size as "packing_size",
            op.uom, null::double precision,
            null::uuid, NULL, NULL, op.batch_id, op.batch_id_ref, null::date, null::date,
            coalesce(ms.name,'') as manifest_no, coalesce(rg.manifested_at, ms.created_at) as manifested_at, coalesce(u6.name, u5.name) as manifested_by, NULL
            from release_goods rg
            left join users u1 on u1.id = rg.creator_id 
            inner join order_products op on rg.id = op.release_good_id
            left join shipping_orders so on so.id = rg.shipping_order_id  
            left join users u4 on u4.id = rg.accepted_by_id 
            left join manifests ms on ms.id = rg.manifest_id
            left join users u5 on u5.id = ms.creator_id
            left join users u6 on u6.id = rg.manifested_by_id
            inner join temp_products p on p.id = op.product_id
            where rg.bizplace_id = $2 and rg.domain_id = $1
            and rg.created_at >= $3 and rg.created_at <= $4
            and rg.assigned_inventory = false
            ${status ? `and rg.status = '${status.value}' ` : ``}
            ${priorityDelivery ? `and rg.priority_delivery = ${priorityDelivery.value} ` : ``}
            ${innerQueryFilters2}
            and rg.assigned_inventory = false
            and op.release_qty > 0
          ) src2
          where 1=1`}
        )
      `, [context.state.domain.id, bizplace.id, fromDate.value, toDate.value, bizplace.name, bizplace.description]);
            console.timeEnd('temp');
            await tx.query(`
        create temp table temp_outbound_order_worksheet on commit drop as ( 
          select oi.id, w.started_at, w.ended_at, w.type, w.status from temp_outbound_order_report oi 
          inner join worksheet_details wd on wd.target_inventory_id = oi.id
          inner join worksheets w on w.id = wd.worksheet_id
          where oi.id is not null
        )
        `);
            const total = await tx.query(`
        select count(*) from temp_outbound_order_report oi
        left join temp_outbound_order_worksheet wpack on wpack.id = oi.id and wpack.type= 'PACKING'
        WHERE 1=1
        ${byPackingComplete.value
                ? `and wpack.ended_at BETWEEN '${fromDate.value}' and '${toDate.value}' and wpack.status = 'DONE'`
                : ''}
      `);
            console.time('result');
            const result = await tx.query(`
        select *,  
        round((qty * unit_volume)::numeric ,4) as total_volume, 
        round((qty * unit_nett_weight)::numeric ,4) as total_unit_nett_weight, 
        round((qty * unit_gross_weight)::numeric ,4) as total_unit_gross_weight
        from (
          select oi.*,
          wpick.started_at as picking_start, wpick.ended_at as picking_complete,
          wpack.started_at as packing_start, wpack.ended_at as packing_complete,
          wsort.started_at as sorting_start, wsort.ended_at as sorting_complete,
          wload.started_at as loading_start, wload.ended_at as loading_complete,
          coalesce(delivery_address, concat(cp.address, cp.address_2)) as "delivery_address",
          coalesce((select volume from product_details pd where pd.id = oi.product_detail_id  
          order by created_at desc
          fetch first 1 rows only),0) as unit_volume,
          coalesce((select nett_weight from product_details pd where pd.id = oi.product_detail_id  
          order by created_at desc
          fetch first 1 rows only),0) as unit_nett_weight,
          coalesce((select gross_weight from product_details pd where pd.id = oi.product_detail_id  
          order by created_at desc
          fetch first 1 rows only),0) as unit_gross_weight,
          coalesce((select weight_unit from product_details pd where pd.id = oi.product_detail_id  
          order by created_at desc
          fetch first 1 rows only),'') as weight_unit,
          coalesce((select unit_cost from reduced_inventory_histories rih where 
            rih.ref_order_id::uuid = oi.id and 
            rih.inventory_id::uuid = oi.inventory_id and
            rih.transaction_type = 'PICKING'
            order by created_at desc
            fetch first 1 rows only), oi.unit_cost, 0) as unit_cost
          from temp_outbound_order_report oi
          left join contact_points cp on cp.id = oi.contact_point_ref_id
          left join temp_outbound_order_worksheet wpick on wpick.id = oi.id 
            and (wpick.type= 'PICKING' OR wpick.type = 'BATCH_PICKING')  
          left join temp_outbound_order_worksheet wpack on wpack.id = oi.id 
            and wpack.type= 'PACKING'
          left join temp_outbound_order_worksheet wsort on wsort.id = oi.id 
            and wsort.type= 'SORTING'
          left join temp_outbound_order_worksheet wload on wload.id = oi.id 
            and wload.type= 'LOADING' 
          WHERE 1=1
          ${byPackingComplete.value
                ? `and wpack.ended_at BETWEEN '${fromDate.value}' and '${toDate.value}' and wpack.status = 'DONE'`
                : ''}
          ${byPackingComplete.value ? `ORDER BY wpack.ended_at DESC` : `ORDER BY order_created_at DESC`}
          offset $1 limit $2
        ) src  
      `, [(params.pagination.page - 1) * params.pagination.limit, params.pagination.limit]);
            console.timeEnd('result');
            let items = result.map(itm => {
                return {
                    bizplace: {
                        id: itm.bizplace_id,
                        name: itm.bizplace_name,
                        description: itm.bizplace_description
                    },
                    doNo: itm.delivery_order_no,
                    doDeliveryDate: itm.delivery_order_delivery_date,
                    dispatchedAt: itm.dispatched_at,
                    deliveryAddress: itm.delivery_address,
                    manifestNo: itm.manifest_no,
                    roNo: itm.ro_no,
                    roType: itm.ro_type,
                    status: itm.ro_status,
                    refNo1: itm.ref_no_1,
                    refNo3: itm.ref_no_3,
                    refNo2: itm.ref_no_2,
                    acceptedBy: itm.accepted_by,
                    acceptedAt: itm.accepted_at,
                    orderCreatedBy: itm.order_created_by,
                    orderCreatedAt: itm.order_created_at,
                    pickingStart: itm.picking_start,
                    pickingComplete: itm.picking_complete,
                    packingStart: itm.packing_start,
                    packingComplete: itm.packing_complete,
                    sortingStart: itm.sorting_start,
                    sortingComplete: itm.sorting_complete,
                    loadingStart: itm.loading_start,
                    loadingComplete: itm.loading_complete,
                    product: {
                        id: itm.product_id,
                        sku: itm.product_sku,
                        name: itm.product_name,
                        description: itm.product_description,
                        type: itm.product_type
                    },
                    packType: itm.packing_type,
                    packSize: itm.packing_size,
                    qty: Math.abs(itm.qty),
                    uomValue: Math.abs(itm.uom_value),
                    uom: itm.uom,
                    unitCost: itm.unit_cost,
                    returnToLocationQty: itm.return_to_location_qty,
                    returnToLocationUomValue: itm.return_to_location_uom_value,
                    unitVolume: itm.unit_volume,
                    totalVolume: itm.total_volume,
                    unitNettWeight: itm.unit_nett_weight,
                    totalUnitNettWeight: itm.total_unit_nett_weight,
                    unitGrossWeight: itm.unit_gross_weight,
                    totalUnitGrossWeight: itm.total_unit_gross_weight,
                    weightUnit: itm.weight_unit,
                    palletId: itm.pallet_id,
                    cartonId: itm.carton_id,
                    batchId: itm.batch_id,
                    batchIdRef: itm.batch_id_ref,
                    expirationDate: itm.expiration_date,
                    manufactureDate: itm.manufacture_date,
                    pickingLocation: itm.picking_location,
                    pickedAt: itm.picked_at,
                    pickedBy: itm.picked_by,
                    packedAt: itm.packed_at,
                    packedBy: itm.packed_by,
                    checkedRemarkBy: itm.checked_remark_by,
                    checkedRemarkAt: itm.checked_remark_at,
                    loadedAt: itm.loaded_at,
                    loadedBy: itm.loaded_by,
                    manifestedAt: itm.manifested_at,
                    manifestedBy: itm.manifested_by,
                    binLocation: itm.picking_bin,
                    exportOption: itm.export_option,
                    containerNo: itm.container_no,
                    containerSize: itm.container_size,
                    palletQty: itm.pallet_qty,
                    transportOption: itm.own_transport ? 'Own Transport' : 'Warehouse Transport',
                    vehicleNo: itm.vehicle_no,
                    driverName: itm.driver_name,
                    priorityDelivery: itm.priority_delivery
                };
            });
            return {
                items,
                total: total[0].count
            };
        }
        catch (error) {
            throw error;
        }
    }
};
//# sourceMappingURL=outbound-order-details-report.js.map