代码改变世界

Oracle中对象表的定义,nested table的使用.--附带Route下载的老版本代码

2010-04-15 12:47  Tracy.  阅读(1470)  评论(0编辑  收藏  举报

如下建立的表脚本

DROP TABLE TMS.TMS_OBJ_ROUTE_DATA CASCADE CONSTRAINTS;

CREATE TABLE TMS.TMS_OBJ_ROUTE_DATA
(
  ROUTE_HEADER_COL,
  ROUTE_STOPS_COL      TMS.ROUTE_STOPS,
  PO_COL               TMS.POS,
  STOP_DETAILS_COL  TMS.STOP_DETAILS,
  PO_STOP_DETAILS_COL  TMS.PO_STOP_DETAILS,
  EXPT_TEXT_COL        VARCHAR2(512 BYTE),
  EXPT_CODE_COL        VARCHAR2(10 BYTE),
  SVR_DATE_COL         DATE,
  DEVICE_ID_COL        VARCHAR2(20 BYTE),
  INSTANCEID_COL       INTEGER
)
NESTED TABLE ROUTE_STOPS_COL STORE AS ROUTE_STOPS_ST,
NESTED TABLE PO_COL STORE AS POS_ST,
NESTED TABLE STOP_DETAILS_COL STORE AS STOP_DETAILS_ST,
NESTED TABLE PO_STOP_DETAILS_COL STORE AS PO_STOP_DETAILS_ST,
NESTED TABLE SETTINGS_COL STORE AS SETTINGS_ST

TABLESPACE TMSDATA
PCTUSED    0
PCTFREE    10
INITRANS   1
MAXTRANS   255
STORAGE    (
            INITIAL          104K
            NEXT             104K
            MINEXTENTS       1
            MAXEXTENTS       UNLIMITED
            PCTINCREASE      0
            BUFFER_POOL      DEFAULT
           )
LOGGING
NOCOMPRESS
NOCACHE
NOPARALLEL
MONITORING;


GRANT SELECT ON TMS.TMS_OBJ_ROUTE_DATA TO TMS_GUEST;
在使用中类似这样插入

   INSERT INTO tms_obj_route_data
                  VALUES (p_route_data.route_header, p_route_data.route_stops,
                          p_route_data.stop_pos, p_route_data.stop_details,
                          p_route_data.po_stop_details,
                          'Exception code can not be null when the status is E',
                          v_instance_id);

附录是一个博主老版本route下载的代码,中间使用到了对象表。

 

CREATE OR REPLACE PACKAGE BODY TMS.tms_ws
AS
   FUNCTION fnexceptlist
      RETURN ex_table
   IS
      out_table   ex_table := NEW ex_table (NULL);
      isfirst     BOOLEAN  := TRUE;
   BEGIN
      FOR x IN (SELECT exception_code, exception_code_description,
                       exception_type
                  FROM tms_exception_code
                 WHERE language_code = 'EN'
                   AND exception_type IN ('STOP', 'ITEM'))
      LOOP
         IF NOT isfirst
         THEN
            out_table.EXTEND;
         END IF;

         out_table (out_table.LAST) :=
            NEW ex_rec (x.exception_code,
                        x.exception_code_description,
                        x.exception_type
                       );
         isfirst := FALSE;
      END LOOP;

      RETURN out_table;
   END;

   FUNCTION find_trailer (
      p_truck_route_instance_id         tms_route_header.truck_route_instance_id%TYPE,
      p_trailer_name                    tms_route_header.trailer_id_original_1%TYPE,
      p_dow                             tms_route_header.dow%TYPE,
      p_load_dt                         tms_route_header.host_created_dt%TYPE,
      p_trailer_out               OUT   tms_route_header.trailer_id_original_1%TYPE
   )
      RETURN BOOLEAN
   AS
      --declaration;
      v_trailer_id   tms_route_header.trailer_id_original_1%TYPE;

      CURSOR trailer_data
      IS
         SELECT DISTINCT trl.trailer_name
                    FROM tms_route_header hdr,
                         tms_stop_detail dtl,
                         wms_intf_trailer_content trl
                   WHERE dtl.truck_route_instance_id =
                                                   hdr.truck_route_instance_id
                     AND trl.sub_truck_route_id = hdr.truck_route_id
                     AND trl.sub_dow = hdr.dow
                     AND trl.location_id = dtl.shipping_unit_id
                     AND trl.intf_dt > SYSDATE - 7
                     AND hdr.truck_route_instance_id =
                                                     p_truck_route_instance_id
                     AND trl.trailer_name <> p_trailer_name;
   --end declaration;
   BEGIN
      OPEN trailer_data;

      LOOP
         FETCH trailer_data
          INTO v_trailer_id;

         EXIT WHEN trailer_data%NOTFOUND;

         BEGIN
            --if the trailer_id did not pass the hasbol function already, just skip to the next record.
            IF wms.wms_tms_intf.trailer_has_bol (v_trailer_id,
                                                 p_dow,
                                                 p_load_dt
                                                )
            THEN
               UPDATE tms_route_header
                  SET trailer_id_original_1 = v_trailer_id
                WHERE truck_route_instance_id = p_truck_route_instance_id;

               COMMIT;
               p_trailer_out := v_trailer_id;
               RETURN TRUE;
            END IF;
         EXCEPTION
            WHEN NO_DATA_FOUND
            THEN
               NULL;
         END;
      END LOOP;

      p_trailer_out := p_trailer_name;
      RETURN FALSE;
   END;

   FUNCTION route_download_deviceid (
      p_route_no          NUMBER,
      p_dow               VARCHAR2,
      p_allow_duplicate   NUMBER,
      p_device_id         VARCHAR2
   )
      RETURN route_data
   AS
      v_route_data   route_data
                             := NEW route_data (NULL, NULL, NULL, NULL, NULL);
   BEGIN
      BEGIN
         v_route_data :=
                        route_download (p_route_no, p_dow, p_allow_duplicate);
      EXCEPTION
         WHEN OTHERS
         THEN      --Only the exception throw out is route downloaded already.
            DECLARE
               ERROR_CODE   NUMBER := SQLCODE;
            BEGIN
               IF ERROR_CODE = -20001
               THEN
                  raise_application_error (-20001,
                                           'Route already downloaded.'
                                          );
               END IF;

               IF ERROR_CODE = -20005
               THEN
                  raise_application_error (-20005,
                                           'Route failed auth from wms.'
                                          );
               END IF;

               raise_application_error (-20008,
                                           'ERRCODE:'
                                        || SQLCODE
                                        || ' ERRTEXT:'
                                        || SQLERRM
                                       );
            END;
      END;

      -- When no exception, we record this download, because we throw exception for download it again.
      IF v_route_data.route_header IS NOT NULL
      THEN
         INSERT INTO tms_route_download
                     (truck_route_instance_id, device_id,
                      download_date
                     )
              VALUES (v_route_data.route_header.instance_id, p_device_id,
                      SYSDATE
                     );
      END IF;

      RETURN v_route_data;
   END;

   FUNCTION route_download (
      p_route_no          IN   NUMBER,
      p_dow               IN   VARCHAR2,
      p_allow_duplicate   IN   NUMBER
   )
      RETURN route_data
   AS
      invalid_route_downloaded   EXCEPTION;
      invalid_route_auth         EXCEPTION;
      -- pragma EXCEPTION_INIT(invalid_route_downloaded,-2292);
      v_instance_id              INTEGER;
      v_route_data               route_data
                             := NEW route_data (NULL, NULL, NULL, NULL, NULL);
      v_route_header             route_header;
      v_route_stops              route_stops;
      v_stop_details             stop_details;
      v_pos                      pos;
      v_po_stop_details          po_stop_details;
      v_first_index              BOOLEAN;

      TYPE auth_type IS RECORD (
         t_truck_route_instance_id   tms_route_header.truck_route_instance_id%TYPE,
         t_trailer_name              tms_route_header.trailer_id_original_1%TYPE,
         t_dow                       tms_route_header.dow%TYPE,
         t_load_dt                   tms_route_header.host_created_dt%TYPE,
         t_download_date             tms_route_header.download_date%TYPE
      );

      auth_rec                   auth_type;
   BEGIN
      BEGIN
         SELECT truck_route_instance_id,
                trailer_id_original_1,
                dow,
                host_created_dt,
                download_date
           INTO auth_rec
           FROM (SELECT *
                   FROM (SELECT   rh.truck_route_instance_id,
                                  rh.trailer_id_original_1, rh.dow,
                                  rh.host_created_dt,
                                  (SELECT MIN
                                             (dld.download_date)
                                     FROM tms.tms_route_download dld
                                    WHERE dld.truck_route_instance_id =
                                                    rh.truck_route_instance_id)
                                                                download_date
                             FROM tms.tms_route_header rh
                            WHERE rh.truck_route_id = p_route_no
                              AND rh.dow = p_dow
                              AND rh.delete_flag = 'N'
                              AND rh.scheduled_departure_date > SYSDATE - 6
                         ORDER BY ABS (SYSDATE - rh.scheduled_departure_date)) u
                  WHERE ROWNUM = 1);
      EXCEPTION
         WHEN NO_DATA_FOUND
         THEN
            RETURN v_route_data;                            --emtpy data back
      END;

      IF NOT wms.wms_tms_intf.trailer_has_bol (auth_rec.t_trailer_name,
                                               auth_rec.t_dow,
                                               auth_rec.t_load_dt
                                              )
      THEN
         IF NOT find_trailer (auth_rec.t_truck_route_instance_id,
                              auth_rec.t_trailer_name,
                              auth_rec.t_dow,
                              auth_rec.t_load_dt,
                              auth_rec.t_trailer_name
                             )
         THEN
            RAISE invalid_route_auth;
         --RETURN v_route_data; --empty data back
         END IF;
      END IF;

      v_route_header :=
         NEW route_header (auth_rec.t_truck_route_instance_id,
                           p_route_no,
                           auth_rec.t_dow,
                           auth_rec.t_trailer_name,
                           SYSDATE
                          );
      v_route_data.route_header := v_route_header;
      v_instance_id := v_route_header.instance_id;
      --Fill ROUTE_STOPS
      v_route_stops := NEW route_stops (NULL);

      IF p_allow_duplicate = 0
      THEN
         IF auth_rec.t_download_date IS NOT NULL
         THEN
            RAISE invalid_route_downloaded;
         END IF;
      END IF;

      SELECT   route_stop (s.stop_id,
                           l.location_name,
                           s.location_id,
                           l.address_1,
                           l.address_2,
                           l.city,
                           l.state_abbr,
                           l.alarm_code,
                           s.scheduled_arrival_dt,
                           s.scheduled_departure_dt,
                           s.actual_arrival_dt,
                           s.actual_departure_dt,
                           s.contacts,
                           s.special_instructions,
                           DECODE (s.status, 'OPEN', NULL, s.status),
                           s.exception_code,
                           'Y',
                           s.stop_seq,
                           s.enroute_time,
                           s.exception_comments
                          )
      BULK COLLECT INTO v_route_stops
          FROM tms.tms_route_stop s INNER JOIN tms_location l
               ON l.location_id = s.location_id
         WHERE s.truck_route_instance_id = v_instance_id
           AND s.delete_flag = 'N'
      ORDER BY stop_seq ASC;

      v_route_data.route_stops := v_route_stops;
      --Fill STOP_DETAILS
      v_stop_details := NEW stop_details (NULL);

      SELECT stop_detail (x.stop_detail_id,
                          NULL,
                          SUBSTR (x.task_type, 0, 1),
                          x.shipping_unit_id,
                          x.description,
                          x.package_type,
                          x.status,
                          x.scan_flag,
                          x.exception_code,
                          NULL,
                          x.scan_dt,
                          x.weight,
                          x.weight_uom,
                          x.stop_id,
                          'Y',
                          DECODE (x.exception_code,
                                  NULL, NVL (x.exception_comment,
                                             x.container_id
                                            ),
                                  x.exception_comment
                                 )
                         )
      BULK COLLECT INTO v_stop_details
        FROM tms.tms_stop_detail x
       WHERE truck_route_instance_id = v_instance_id
         AND delete_flag = 'N'
         AND shipping_unit_id <> 'FAKE PALLET';

      v_route_data.stop_details := v_stop_details;
      --Fill POS
      v_pos := NEW pos (NULL);

      SELECT po (x.stop_id,
                 x.po_id,
                 x.delete_flag,
                 x.weight,
                 x.weight_uom,
                 'Y'
                )
      BULK COLLECT INTO v_pos
        FROM tms.tms_po x
       WHERE truck_route_instance_id = v_instance_id AND delete_flag = 'N';

      v_route_data.stop_pos := v_pos;
      --Fill PO_STOP_DETAILS
      v_po_stop_details := NEW po_stop_details (NULL);

      SELECT po_stop_detail (x.stop_detail_id,
                             x.po_id,
                             x.stop_id,
                             x.delete_flag,
                             'Y'
                            )
      BULK COLLECT INTO v_po_stop_details
        FROM tms.tms_po_stop_detail x
       WHERE truck_route_instance_id = v_instance_id AND delete_flag = 'N';

      v_route_data.po_stop_details := v_po_stop_details;
      RETURN v_route_data;
   EXCEPTION
      WHEN NO_DATA_FOUND
      THEN
         RETURN v_route_data;
      WHEN invalid_route_downloaded
      THEN
         raise_application_error (-20001, 'Route already downloaded.');
      WHEN invalid_route_auth
      THEN
         raise_application_error (-20005, 'Route failed auth from wms.');
   END;

   FUNCTION route_download_deviceid_ex (
      p_route_no          IN       NUMBER,
      p_dow               IN       VARCHAR2,
      p_allow_duplicate   IN       NUMBER,
      p_device_id         IN       VARCHAR2,
      o_req_result        OUT      reqresult
   )
      RETURN route_data_ex
   AS
      invalid_route_downloaded   EXCEPTION;
      invalid_route_auth         EXCEPTION;
      -- pragma EXCEPTION_INIT(invalid_route_downloaded,-2292);
      v_instance_id              INTEGER;
      v_route_data               route_data_ex
                          := NEW route_data_ex (NULL, NULL, NULL, NULL, NULL);
      v_route_header             route_header_ex;
      v_route_stops              route_stops;
      v_stop_details             stop_details_ex;
      v_pos                      pos;
      v_po_stop_details          po_stop_details;
      v_first_index              BOOLEAN;

      TYPE auth_type IS RECORD (
         t_truck_route_instance_id   tms_route_header.truck_route_instance_id%TYPE,
         t_trailer_name              tms_route_header.trailer_id_original_1%TYPE,
         t_dow                       tms_route_header.dow%TYPE,
         t_load_dt                   tms_route_header.host_created_dt%TYPE,
         t_download_date             tms_route_header.download_date%TYPE
      );

      auth_rec                   auth_type;
   BEGIN
      BEGIN
         SELECT truck_route_instance_id,
                trailer_id_original_1,
                dow,
                host_created_dt,
                download_date
           INTO auth_rec
           FROM (SELECT *
                   FROM (SELECT   rh.truck_route_instance_id,
                                  rh.trailer_id_original_1, rh.dow,
                                  rh.host_created_dt,
                                  (SELECT MIN
                                             (dld.download_date)
                                     FROM tms.tms_route_download dld
                                    WHERE dld.truck_route_instance_id =
                                                    rh.truck_route_instance_id)
                                                                download_date
                             FROM tms.tms_route_header rh
                            WHERE rh.truck_route_id = p_route_no
                              AND rh.dow = p_dow
                              AND rh.delete_flag = 'N'
                              AND rh.scheduled_departure_date  > SYSDATE - 6
                         ORDER BY rh.truck_route_instance_id DESC) u
                  WHERE ROWNUM = 1);
      EXCEPTION
         WHEN NO_DATA_FOUND
         THEN
            o_req_result :=
               NEW reqresult (0,
                              -20000,
                              'Route download without data.',
                              SYSDATE
                             );
            RETURN v_route_data;                             --emtpy data back
      END;

      IF NOT wms.wms_tms_intf.trailer_has_bol (auth_rec.t_trailer_name,
                                               auth_rec.t_dow,
                                               auth_rec.t_load_dt
                                              )
      THEN
         IF NOT find_trailer (auth_rec.t_truck_route_instance_id,
                              auth_rec.t_trailer_name,
                              auth_rec.t_dow,
                              auth_rec.t_load_dt,
                              auth_rec.t_trailer_name
                             )
         THEN
            RAISE invalid_route_auth;
         END IF;
      END IF;

      v_route_header :=
         NEW route_header_ex (auth_rec.t_truck_route_instance_id,
                              p_route_no,
                              auth_rec.t_dow,
                              auth_rec.t_trailer_name,
                              SYSDATE,
                              '',
                              '',
                              ''
                             );
      v_route_data.route_header := v_route_header;
      v_instance_id := v_route_header.instance_id;
      --Fill ROUTE_STOPS
      v_route_stops := NEW route_stops (NULL);

      IF p_allow_duplicate = 0
      THEN
         IF auth_rec.t_download_date IS NOT NULL
         THEN
            RAISE invalid_route_downloaded;
         END IF;
      END IF;

      SELECT   route_stop (s.stop_id,
                           l.location_name,
                           s.location_id,
                           l.address_1,
                           l.address_2,
                           l.city,
                           l.state_abbr,
                           l.alarm_code,
                           s.scheduled_arrival_dt,
                           s.scheduled_departure_dt,
                           s.actual_arrival_dt,
                           s.actual_departure_dt,
                           s.contacts,
                           s.special_instructions,
                           DECODE (s.status, 'OPEN', NULL, s.status),
                           s.exception_code,
                           'Y',
                           s.stop_seq,
                           s.enroute_time,
                           s.exception_comments
                          )
      BULK COLLECT INTO v_route_stops
          FROM tms.tms_route_stop s INNER JOIN tms_location l
               ON l.location_id = s.location_id
         WHERE s.truck_route_instance_id = v_instance_id
           AND s.delete_flag = 'N'
      ORDER BY stop_seq ASC;

      v_route_data.route_stops := v_route_stops;
      --Fill STOP_DETAILS
      v_stop_details := NEW stop_details_ex (NULL);

      SELECT stop_detail_ex (stop_detail_id,
                             NULL,
                             SUBSTR (task_type, 0, 1),
                             shipping_unit_id,
                             description,
                             package_type,
                             status,
                             scan_flag,
                             exception_code,
                             NULL,
                             scan_dt,
                             weight,
                             weight_uom,
                             stop_id,
                             'Y',
                             exception_comment,
                             container_id,
                             next_detail_id,
                             'N',
                             item_id,
                             ''
                            )
      BULK COLLECT INTO v_stop_details
        FROM tms.tms_stop_detail
       WHERE truck_route_instance_id = v_instance_id
         AND delete_flag = 'N'
         AND shipping_unit_id <> 'FAKE PALLET';

      v_route_data.stop_details := v_stop_details;
      --Fill POS
      v_pos := NEW pos (NULL);

      SELECT po (x.stop_id,
                 x.po_id,
                 x.delete_flag,
                 x.weight,
                 x.weight_uom,
                 'Y'
                )
      BULK COLLECT INTO v_pos
        FROM tms.tms_po x
       WHERE truck_route_instance_id = v_instance_id AND delete_flag = 'N';

      v_route_data.stop_pos := v_pos;
      --Fill PO_STOP_DETAILS
      v_po_stop_details := NEW po_stop_details (NULL);

      SELECT po_stop_detail (x.stop_detail_id,
                             x.po_id,
                             x.stop_id,
                             x.delete_flag,
                             'Y'
                            )
      BULK COLLECT INTO v_po_stop_details
        FROM tms.tms_po_stop_detail x
       WHERE truck_route_instance_id = v_instance_id AND delete_flag = 'N';

      v_route_data.po_stop_details := v_po_stop_details;

      INSERT INTO tms_route_download
                  (truck_route_instance_id, device_id, download_date
                  )
           VALUES (v_route_data.route_header.instance_id, p_device_id, SYSDATE
                  );

      o_req_result :=
                 NEW reqresult (1, 0, 'Route download successfully.', SYSDATE);
      RETURN v_route_data;
   EXCEPTION
      --it's impossible to go to here, bulk collect into will not cause no_data_found .
      /*
         WHEN NO_DATA_FOUND
         THEN
            o_req_result :=
               NEW reqresult (0, -20000, 'Route download without data.',
                              SYSDATE);
            RETURN v_route_data;
            */
      WHEN invalid_route_downloaded
      THEN
         o_req_result :=
               NEW reqresult (0, -20001, 'Route already downloaded.',
                              SYSDATE);
         RETURN v_route_data;
      --raise_application_error (-20001, 'Route already downloaded.');
      WHEN invalid_route_auth
      THEN
         o_req_result :=
             NEW reqresult (0, -20005, 'Route failed auth from wms.',
                            SYSDATE);
         RETURN v_route_data;
      WHEN OTHERS
      THEN
         o_req_result := NEW reqresult (0, SQLCODE, SQLERRM, SYSDATE);
         RETURN v_route_data;
   --  raise_application_error (-20005, 'Route failed auth from wms.');
   END;

   FUNCTION data_to_hh (p_instance_id IN NUMBER, last_update IN DATE)
      RETURN route_data
   AS
      v_route_data        route_data
                             := NEW route_data (NULL, NULL, NULL, NULL, NULL);
      v_route_header      route_header;
      v_route_stops       route_stops;
      v_stop_details      stop_details;
      v_pos               pos;
      v_po_stop_details   po_stop_details;
      v_first_index       BOOLEAN;
      p_lastupdate        DATE            := last_update;
   BEGIN
      SELECT route_header (truck_route_instance_id,
                           truck_route_id,
                           dow,
                           trailer_id_original_1,
                           SYSDATE
                          )
        INTO v_route_header
        FROM tms.tms_route_header
       WHERE truck_route_instance_id = p_instance_id;

      v_route_data.route_header := v_route_header;
      --Fill ROUTE_STOPS
      v_route_stops := NEW route_stops (NULL);
      v_first_index := TRUE;

      SELECT   route_stop (s.stop_id,
                           l.location_name,
                           s.location_id,
                           l.address_1,
                           l.address_2,
                           l.city,
                           l.state_abbr,
                           l.alarm_code,
                           s.scheduled_arrival_dt,
                           s.scheduled_departure_dt,
                           s.actual_arrival_dt,
                           s.actual_departure_dt,
                           s.contacts,
                           s.special_instructions,
                           s.status,
                           s.exception_code,
                           'Y',
                           s.stop_seq,
                           s.enroute_time,
                           s.exception_comments
                          )
      BULK COLLECT INTO v_route_stops
          FROM tms.tms_route_stop s INNER JOIN tms_location l
               ON l.location_id = s.location_id
         WHERE s.truck_route_instance_id = p_instance_id
           AND s.delete_flag = 'N'
           AND s.last_update > p_lastupdate
      ORDER BY stop_seq ASC;

      v_route_data.route_stops := v_route_stops;
      --Fill STOP_DETAILS
      v_stop_details := NEW stop_details (NULL);

      SELECT stop_detail (stop_detail_id,
                          NULL,
                          SUBSTR (task_type, 0, 1),
                          shipping_unit_id,
                          description,
                          package_type,
                          DECODE (status, 'OPEN', NULL, status),
                          scan_flag,
                          exception_code,
                          NULL,
                          scan_dt,
                          weight,
                          weight_uom,
                          stop_id,
                          'Y',
                          DECODE (exception_code,
                                  NULL, NVL (exception_comment, container_id),
                                  exception_comment
                                 )
                         )
      BULK COLLECT INTO v_stop_details
        FROM tms.tms_stop_detail
       WHERE truck_route_instance_id = p_instance_id
         AND delete_flag = 'N'
         AND last_update > p_lastupdate
         AND shipping_unit_id <> 'FAKE PALLET';

      v_route_data.stop_details := v_stop_details;
      --Fill POS
      v_pos := NEW pos (NULL);

      SELECT po (x.stop_id,
                 x.po_id,
                 x.delete_flag,
                 x.weight,
                 x.weight_uom,
                 'Y'
                )
      BULK COLLECT INTO v_pos
        FROM tms.tms_po x
       WHERE truck_route_instance_id = p_instance_id
         AND delete_flag = 'N'
         AND last_update > p_lastupdate;

      v_route_data.stop_pos := v_pos;
      --Fill PO_STOP_DETAILS
      v_po_stop_details := NEW po_stop_details (NULL);

      SELECT po_stop_detail (x.stop_detail_id,
                             x.po_id,
                             x.stop_id,
                             x.delete_flag,
                             'Y'
                            )
      BULK COLLECT INTO v_po_stop_details
        FROM tms.tms_po_stop_detail x
       WHERE truck_route_instance_id = p_instance_id
         AND delete_flag = 'N'
         AND last_update > p_lastupdate;

      v_route_data.po_stop_details := v_po_stop_details;
      RETURN v_route_data;
   EXCEPTION
      WHEN NO_DATA_FOUND
      THEN
         RETURN v_route_data;
   END;

   FUNCTION data_to_hh_ex (p_instance_id IN NUMBER, last_update IN DATE)
      RETURN route_data_ex
   AS
      v_route_data        route_data_ex
                          := NEW route_data_ex (NULL, NULL, NULL, NULL, NULL);
      v_route_header      route_header_ex;
      v_route_stops       route_stops;
      v_stop_details      stop_details_ex;
      v_pos               pos;
      v_po_stop_details   po_stop_details;
      v_first_index       BOOLEAN;
      p_lastupdate        DATE            := last_update;
   BEGIN
      SELECT route_header_ex (truck_route_instance_id,
                              truck_route_id,
                              dow,
                              trailer_id_original_1,
                              SYSDATE,
                              '',
                              '',
                              ''
                             )
        INTO v_route_header
        FROM tms.tms_route_header
       WHERE truck_route_instance_id = p_instance_id;

      v_route_data.route_header := v_route_header;
      --Fill ROUTE_STOPS
      v_route_stops := NEW route_stops (NULL);
      v_first_index := TRUE;

      SELECT   route_stop (s.stop_id,
                           l.location_name,
                           s.location_id,
                           l.address_1,
                           l.address_2,
                           l.city,
                           l.state_abbr,
                           l.alarm_code,
                           s.scheduled_arrival_dt,
                           s.scheduled_departure_dt,
                           s.actual_arrival_dt,
                           s.actual_departure_dt,
                           s.contacts,
                           s.special_instructions,
                           s.status,
                           s.exception_code,
                           'Y',
                           s.stop_seq,
                           s.enroute_time,
                           s.exception_comments
                          )
      BULK COLLECT INTO v_route_stops
          FROM tms.tms_route_stop s INNER JOIN tms_location l
               ON l.location_id = s.location_id
         WHERE s.truck_route_instance_id = p_instance_id
           AND s.delete_flag = 'N'
           AND s.last_update > p_lastupdate
      ORDER BY stop_seq ASC;

      v_route_data.route_stops := v_route_stops;
      --Fill STOP_DETAILS
      v_stop_details := NEW stop_details_ex (NULL);

      SELECT stop_detail_ex (stop_detail_id,
                             NULL,
                             SUBSTR (task_type, 0, 1),
                             shipping_unit_id,
                             description,
                             package_type,
                             DECODE (status, 'OPEN', NULL, status),
                             scan_flag,
                             exception_code,
                             NULL,
                             scan_dt,
                             weight,
                             weight_uom,
                             stop_id,
                             'Y',
                             exception_comment,
                             container_id,
                             next_detail_id,
                             'N',
                             '',
                             ''
                            )
      BULK COLLECT INTO v_stop_details
        FROM tms.tms_stop_detail
       WHERE truck_route_instance_id = p_instance_id
         AND delete_flag = 'N'
         AND last_update > p_lastupdate
         AND shipping_unit_id <> 'FAKE PALLET';

      v_route_data.stop_details := v_stop_details;
      --Fill POS
      v_pos := NEW pos (NULL);

      SELECT po (x.stop_id,
                 x.po_id,
                 x.delete_flag,
                 x.weight,
                 x.weight_uom,
                 'Y'
                )
      BULK COLLECT INTO v_pos
        FROM tms.tms_po x
       WHERE truck_route_instance_id = p_instance_id
         AND delete_flag = 'N'
         AND last_update > p_lastupdate;

      v_route_data.stop_pos := v_pos;
      --Fill PO_STOP_DETAILS
      v_po_stop_details := NEW po_stop_details (NULL);

      SELECT po_stop_detail (x.stop_detail_id,
                             x.po_id,
                             x.stop_id,
                             x.delete_flag,
                             'Y'
                            )
      BULK COLLECT INTO v_po_stop_details
        FROM tms.tms_po_stop_detail x
       WHERE truck_route_instance_id = p_instance_id
         AND delete_flag = 'N'
         AND last_update > p_lastupdate;

      v_route_data.po_stop_details := v_po_stop_details;
      RETURN v_route_data;
   EXCEPTION
      WHEN NO_DATA_FOUND
      THEN
         RETURN v_route_data;
   END;

   FUNCTION route_suggest (p_route_no NUMBER, p_dow VARCHAR2)
      RETURN suggest_route_table
   AS
      v_suggest_data_table   suggest_route_table
                                            := NEW suggest_route_table (NULL);
      v_stop_status_table    stop_status_table
                                              := NEW stop_status_table (NULL);
      v_first_index          BOOLEAN;
      v_first_idx            BOOLEAN;
      v_routestatus          VARCHAR2 (3);
   BEGIN
      v_first_index := TRUE;

      FOR x IN
         (WITH target_stops AS
               (SELECT DISTINCT campus_id location_id
                           FROM wms_truck_route_vw
                          WHERE truck_route_id = p_route_no
                            AND truck_stop_seq > 1),
               candidate_routes AS
               (SELECT   /*+ leading(h) */
                         truck_route_id, dow, h.truck_route_instance_id
                FROM     tms_route_header h,
                         tms_route_stop s,
                         target_stops t,
                         tms_location loc
                   WHERE h.scheduled_departure_date > SYSDATE - 6
                     AND h.truck_route_instance_id = s.truck_route_instance_id
                     AND t.location_id = s.location_id
                     AND loc.location_id = s.location_id
                     AND h.delete_flag = 'N'
                GROUP BY truck_route_id, dow, h.truck_route_instance_id
                  HAVING COUNT (*) > 1
                     AND COUNT (DECODE (loc.hub, 'Y', NULL, 1)) > 0)
          SELECT   truck_route_id, dow,
                   (SELECT NVL (trailer_id_original_1,
                                'UNKNOWN')
                      FROM tms_route_header rheader
                     WHERE can.truck_route_instance_id =
                                 rheader.truck_route_instance_id
                       AND ROWNUM <= 1) trailer_name,
                   (SELECT host_created_dt
                      FROM tms_route_header rheader
                     WHERE can.truck_route_instance_id =
                                     rheader.truck_route_instance_id
                       AND ROWNUM <= 1) load_day,
                   (SELECT MIN (dld.download_date)
                      FROM tms.tms_route_download dld
                     WHERE dld.truck_route_instance_id =
                                    can.truck_route_instance_id)
                                                                download_date,
                   truck_route_instance_id
              FROM candidate_routes can
          ORDER BY truck_route_instance_id DESC)
      LOOP
         IF NOT v_first_index
         THEN
            v_suggest_data_table.EXTEND;
         END IF;

         v_first_index := FALSE;
         v_first_idx := TRUE;
         v_stop_status_table := NEW stop_status_table (NULL);

         --clear it to regain the records
         FOR y IN (SELECT   stop_id, location_name, decode(status,'OPEN',null,status) status, stop_seq
                       FROM tms_route_stop s INNER JOIN tms_location l
                            ON l.location_id = s.location_id
                      WHERE s.truck_route_instance_id =
                                                     x.truck_route_instance_id
                        AND s.delete_flag = 'N'
                   ORDER BY stop_seq ASC)
         LOOP
            IF NOT v_first_idx
            THEN
               v_stop_status_table.EXTEND;
            END IF;

            v_first_idx := FALSE;
            v_stop_status_table (v_stop_status_table.LAST) :=
               NEW stop_status (y.stop_id,
                                y.location_name,
                                y.status,
                                y.stop_seq
                               );
         END LOOP;

         IF NOT wms.wms_tms_intf.trailer_has_bol (x.trailer_name,
                                                  x.dow,
                                                  x.load_day
                                                 )
         THEN
            v_routestatus := 'THB';        -- brief word for trailer_has bool
         ELSE
            v_routestatus := 'NML';                                 --normal;
         END IF;

         v_suggest_data_table (v_suggest_data_table.LAST) :=
            NEW suggest_route_data (v_stop_status_table,
                                    x.truck_route_id,
                                    x.dow,
                                    x.download_date,
                                    v_routestatus
                                   );
      END LOOP;

      RETURN v_suggest_data_table;
   END;

   FUNCTION route_update_eod (
      p_route_data      IN   route_data,
      p_is_end_of_day   IN   INTEGER,
      p_dt_eod          IN   DATE,
      p_device_id            VARCHAR2
   )
      RETURN id_update
   AS
---------------------------------------------*Declare some variable*---------------------------------------------------------
      constant_unattachpo   CHAR (14)                     := 'Unattached POs';
      v_route_stops         route_stops;
      v_stop_details        stop_details;
      v_pos                 pos;
      v_po_stop_details     po_stop_details;
      v_route_stop          route_stop;
      v_stop_detail         stop_detail;
      v_po_stop_detail      po_stop_detail;
      v_po                  po;
      v_last_update         DATE                                  := SYSDATE;
      v_eod                 DATE;
      v_instance_id         INTEGER                               := 0;
      v_data_counter        INTEGER                               := 0;
      v_isfirst             BOOLEAN                               := TRUE;
      v_new_id              INTEGER;
      v_unattach_exist      INTEGER                               := 0;
      t_idupdate            id_update;
      tc_idmap              id_map                       := NEW id_map (NULL);
      t_idrelation          id_relation;
      v_location_id         tms.tms_route_stop.location_id%TYPE;
      v_count               NUMBER;
      v_pallet_count        NUMBER;
      v_num                 NUMBER                                := 0;
      v_counterr            NUMBER (4);
      v_alreadyrun          NUMBER                                := 0;
      miss_route_status     EXCEPTION;
      v_miss_stp            INTEGER;
      v_cntempty            INTEGER                               := 0;
      v_cntsd               INTEGER                               := 0;
--------------------------------------------------*End declare*---------------------------------------------------------------
   BEGIN
      --get object to local variable.
      --v_route_data := p_route_data;
      v_route_stops := p_route_data.route_stops;
      v_stop_details := p_route_data.stop_details;
      v_po_stop_details := p_route_data.po_stop_details;
      v_pos := p_route_data.stop_pos;

      --This if for initialize the empty collections, so we do not need initialize it later.
      IF v_route_stops IS NULL
      THEN
         --  ex_route_stops := NEW route_stops (NULL);
         v_route_stops := NEW route_stops (NULL);
      END IF;

      IF v_pos IS NULL
      THEN
         -- ex_pos := NEW pos (NULL);
         v_pos := NEW pos (NULL);
      END IF;

      IF v_stop_details IS NULL
      THEN
         -- ex_stop_details := NEW stop_details (NULL);
         v_stop_details := NEW stop_details (NULL);
      END IF;

      IF v_po_stop_details IS NULL
      THEN
         --  ex_po_stop_details := NEW po_stop_details (NULL);
         v_po_stop_details := NEW po_stop_details (NULL);
      END IF;

------End initialize the empty collections
      v_instance_id := p_route_data.route_header.instance_id;

      --Insert into the log table when end of day, so we know they do this operation.
      IF p_is_end_of_day = 1
      THEN
         INSERT INTO tms_handheld_log
              VALUES (SUBSTR (p_device_id, 1, 20), SYSDATE, 0,
                      'BGL-ENDOFDAY', TO_CHAR (v_instance_id), SYSDATE,
                      tms_handheld_seq.NEXTVAL);
      END IF;

      UPDATE tms_route_header
         SET last_update = v_last_update
       WHERE truck_route_instance_id = v_instance_id;


      --loop for route_stop
      LOOP
         EXIT WHEN v_route_stops.FIRST IS NULL;
         v_route_stop := v_route_stops (v_route_stops.NEXT (v_data_counter));

         UPDATE tms_route_stop
            SET actual_arrival_dt = v_route_stop.actual_arrival,
                enroute_time = v_route_stop.enroute_dt,
                actual_departure_dt = v_route_stop.actual_departure,
                special_instructions = v_route_stop.special_instructions,
                exception_code = v_route_stop.exception_code,
                exception_comments = v_route_stop.exception_comments,
                status =
                   DECODE (v_route_stop.status,
                           NULL, 'OPEN',
                           v_route_stop.status
                          ),
                last_update = v_last_update
          WHERE truck_route_instance_id = v_instance_id
            AND stop_id = v_route_stop.stop_id;

         IF v_stop_details.COUNT = 0
         --If we do not upload every thing ,we erase the unattachedPo.
         THEN
            DELETE FROM tms_stop_detail
                  WHERE stop_id = v_route_stop.stop_id
                    AND shipping_unit_id = constant_unattachpo;

            DELETE FROM tms_po_stop_detail
                  WHERE shipping_unit_id = constant_unattachpo
                    AND stop_id = v_route_stop.stop_id;
         END IF;

         v_data_counter := v_data_counter + 1;
         EXIT WHEN v_data_counter >= p_route_data.route_stops.COUNT;
      END LOOP;

      --loop for stop_detail
      v_unattach_exist := 0;
      v_data_counter := 0;

      LOOP
         EXIT WHEN v_stop_details.FIRST IS NULL;
         v_stop_detail :=
                        v_stop_details (v_stop_details.NEXT (v_data_counter));

         IF     v_stop_detail.scan_timestamp IS NULL
            AND v_stop_detail.line_status = 'E'
         THEN
            v_stop_detail.scan_timestamp := SYSDATE;
         END IF;

         UPDATE tms_stop_detail
            SET shipping_unit_id = v_stop_detail.scan_id,
                intf_status =
                   DECODE (v_stop_detail.scan_timestamp,
                           NULL, intf_status,
                           scan_dt, intf_status,
                           'READY'
                          ),
                status = v_stop_detail.line_status,
                scan_flag = v_stop_detail.scan_ind,
                scan_dt = v_stop_detail.scan_timestamp,
                description = v_stop_detail.description,
                weight = v_stop_detail.weight,
                weight_uom = v_stop_detail.weight_uom,
                exception_code = v_stop_detail.exception_code,
                exception_comment =
                   DECODE (v_stop_detail.exception_code,
                           NULL, NULL,
                           v_stop_detail.exception_comment
                          ),                --v_stop_detail.exception_comment,
                package_type = v_stop_detail.package_type,
                last_update = v_last_update,
                container_id =
                   DECODE (v_stop_detail.exception_code,
                           NULL, v_stop_detail.exception_comment,
                           NULL
                          )
          --when the exceptionCode is null,we set the value to the column.
         WHERE  truck_route_instance_id = v_instance_id
            AND stop_id = v_stop_detail.stop_id
            AND shipping_unit_id = v_stop_detail.scan_id
            AND task_type != 'DROP'
            AND task_type =
                   DECODE (v_stop_detail.pick_up_drop_off_ind,
                           'D', 'DROP',
                           'P', 'PICK',
                           'E', 'EMPT',
                           'L', 'LOAD',
                           'ERR'
                          );

         v_cntsd := SQL%ROWCOUNT;

         IF v_cntsd = 0
         THEN
            UPDATE tms_stop_detail
               SET shipping_unit_id = v_stop_detail.scan_id,
                   intf_status =
                      DECODE (v_stop_detail.scan_timestamp,
                              NULL, intf_status,
                              scan_dt, intf_status,
                              'READY'
                             ),
                   status = v_stop_detail.line_status,
                   scan_flag = v_stop_detail.scan_ind,
                   stop_id = v_stop_detail.stop_id,
                   scan_dt = v_stop_detail.scan_timestamp,
                   description = v_stop_detail.description,
                   weight = v_stop_detail.weight,
                   weight_uom = v_stop_detail.weight_uom,
                   exception_code = v_stop_detail.exception_code,
                   exception_comment =
                      DECODE (v_stop_detail.exception_code,
                              NULL, NULL,
                              v_stop_detail.exception_comment
                             ),             --v_stop_detail.exception_comment,
                   package_type = v_stop_detail.package_type,
                   last_update = v_last_update,
                   container_id =
                      DECODE (v_stop_detail.exception_code,
                              NULL, v_stop_detail.exception_comment,
                              NULL
                             )
             --when the exceptionCode is null,we set the value to the column.
            WHERE  truck_route_instance_id = v_instance_id
               -- AND stop_id = v_stop_detail.stop_id
               AND shipping_unit_id = v_stop_detail.scan_id
               AND task_type = 'DROP'
               AND task_type =
                      DECODE (v_stop_detail.pick_up_drop_off_ind,
                              'D', 'DROP',
                              'P', 'PICK',
                              'E', 'EMPT',
                              'L', 'LOAD',
                              'ERR'
                             );

            v_cntsd := SQL%ROWCOUNT;
         END IF;

         IF v_cntsd = 0
         THEN
            IF v_stop_detail.scan_id = constant_unattachpo
            THEN
               v_unattach_exist := 2;
            END IF;

            SELECT tms.tms_bgl_route_stop_detail_seq.NEXTVAL
              INTO v_new_id
              FROM DUAL;

            INSERT INTO tms_temp_stop_detail
                 VALUES (v_new_id, v_stop_detail.stop_detail_id);

            v_stop_detail.stop_detail_id := v_new_id;

            INSERT INTO tms_stop_detail
                        (stop_detail_id, truck_route_instance_id,
                         stop_id, destination_id, trailer_id,
                         task_type,
                         shipping_unit_id, description,
                         package_type,
                         weight,
                         weight_uom, host_created_dt,
                         status,
                         exception_code,
                         scan_flag,
                         scan_dt, last_update,
                         exception_comment,
                         container_id,
                         intf_status
                        )
                 VALUES (v_stop_detail.stop_detail_id, v_instance_id,
                         v_stop_detail.stop_id, 0, '',
                         DECODE (v_stop_detail.pick_up_drop_off_ind,
                                 'D', 'DROP',
                                 'P', 'PICK',
                                 'E', 'EMPT',
                                 'L', 'LOAD',
                                 'ERR'
                                ),
                         v_stop_detail.scan_id, v_stop_detail.description,
                         v_stop_detail.package_type,
                         NVL (v_stop_detail.weight, 0),
                         v_stop_detail.weight_uom, SYSDATE,
                         v_stop_detail.line_status,
                         v_stop_detail.exception_code,
                         v_stop_detail.scan_ind,
                         v_stop_detail.scan_timestamp, SYSDATE,
                         DECODE (v_stop_detail.exception_code,
                                 NULL, NULL,
                                 v_stop_detail.exception_comment
                                ),
                         --  v_stop_detail.exception_comment,
                         DECODE (v_stop_detail.exception_code,
                                 NULL, v_stop_detail.exception_comment,
                                 NULL
                                ),
                         'READY'
                        );
         ELSE
            IF v_stop_detail.stop_detail_id < 0
            THEN
               --For some reason, the negative value is not updated in client and it's uploaded again,
               --the oracle side get the right value, we just make the value correct so po_stop_detail will not inserted wrong value.
               SELECT stop_detail_id
                 INTO v_new_id
                 FROM tms_stop_detail
                WHERE truck_route_instance_id = v_instance_id
                  AND stop_id = v_stop_detail.stop_id
                  AND shipping_unit_id = v_stop_detail.scan_id;

               /* This is not nesscary since the unique key is stop_id and scan_id.

               AND task_type =
                      DECODE (v_stop_detail.pick_up_drop_off_ind,
                              'D', 'DROP',
                              'P', 'PICK',
                              'E', 'EMPT',
                              'L', 'LOAD'
                             );
                    */
               INSERT INTO tms_temp_stop_detail
                    VALUES (v_new_id, v_stop_detail.stop_detail_id);
            --At this point , the temp table had the correct positive stop_detail_id that we can handle the
            --po_stop_detail properly.
            END IF;

            IF v_stop_detail.scan_id = constant_unattachpo
            THEN
               v_unattach_exist := 1;
            END IF;
         END IF;

         --if the error code has issue. We can record it into our object table.
         SELECT COUNT (stop_detail_id)
           INTO v_counterr
           FROM tms_stop_detail
          WHERE exception_code IS NULL
            AND status = 'E'
            AND stop_detail_id = v_stop_detail.stop_detail_id;

         IF v_counterr > 0 AND v_alreadyrun = 0
         THEN
            --if insert once, we will not insert for another loop;
          null;
            v_alreadyrun := 1;
         END IF;

         --generate the location code and the number of composite pallets which were dropped off
         BEGIN
            BEGIN
               SELECT   s.location_id, COUNT (*)
                   INTO v_location_id, v_count
                   FROM tms_stop_detail d, tms.tms_route_stop s
                  WHERE d.stop_id = s.stop_id
                    AND d.stop_id = v_stop_detail.stop_id
                    AND d.shipping_unit_id = v_stop_detail.scan_id
                    AND d.truck_route_instance_id = s.truck_route_instance_id
                    AND d.truck_route_instance_id = v_instance_id
                    AND composite_pallet (d.shipping_unit_id) = 1
                    AND d.task_type IN ('DROP')
                    AND d.status IN ('Y')
               GROUP BY d.task_type, s.location_id;

               SELECT COUNT (*)
                 INTO v_num
                 FROM tms_empty_pallet
                WHERE location_id = v_location_id;

               IF v_num = 0
               THEN
                  INSERT INTO tms_empty_pallet
                       VALUES (v_location_id, v_count);
               ELSE
                  UPDATE tms_empty_pallet
                     SET pallet_count = pallet_count + v_count
                   WHERE location_id = v_location_id;
               END IF;
            EXCEPTION
               WHEN OTHERS
               THEN
                  DECLARE
                     ERROR_CODE   NUMBER         := SQLCODE;
                     error_msg    VARCHAR2 (512) := SQLERRM;
                  BEGIN
                     IF ERROR_CODE != 100
                     THEN                                     --no data found
                        null;
                     END IF;
                  END;
            END;

            BEGIN
               v_num := 0;

               FOR inx IN (SELECT   s.location_id, d.status,
                                    d.exception_code, COUNT (*) count_num
                               FROM tms.tms_stop_detail d,
                                    tms.tms_route_stop s
                              WHERE d.stop_id = s.stop_id
                                AND d.stop_id = v_stop_detail.stop_id
                                AND d.shipping_unit_id = v_stop_detail.scan_id
                                AND d.truck_route_instance_id =
                                                     s.truck_route_instance_id
                                AND d.truck_route_instance_id = v_instance_id
                                AND d.task_type IN ('EMPT')
                                AND d.status IN ('Y', 'E')
                           GROUP BY s.location_id, d.status, d.exception_code
                           ORDER BY d.status DESC)
               LOOP
                  v_num := v_num + 1;

                  SELECT COUNT (*)
                    INTO v_count
                    --the number of composite pallets dropped off on this store
                  FROM   tms_stop_detail d, tms.tms_route_stop s
                   WHERE d.stop_id = s.stop_id
                     AND d.stop_id = v_stop_detail.stop_id
                     AND d.truck_route_instance_id = s.truck_route_instance_id
                     AND d.truck_route_instance_id = v_instance_id
                     AND composite_pallet (d.shipping_unit_id) = 1
                     AND d.task_type IN ('DROP')
                     AND d.status IN ('Y');

                  IF v_num = 1
                  THEN
                     IF inx.status = 'Y'
                     THEN
                        SELECT pallet_count
                          INTO v_pallet_count
                          FROM tms_empty_pallet
                         WHERE location_id = inx.location_id;

                        IF inx.count_num >= v_pallet_count
                        THEN
                           UPDATE tms_empty_pallet
                              SET pallet_count = v_count
                            WHERE location_id = inx.location_id;
                        ELSE
                           UPDATE tms_empty_pallet
                              SET pallet_count = pallet_count - inx.count_num
                            WHERE location_id = inx.location_id;
                        END IF;
                     ELSIF inx.status = 'E' AND inx.exception_code = 'MISS'
                     THEN
                        UPDATE tms_empty_pallet
                           SET pallet_count = v_count
                         WHERE location_id = inx.location_id;
                     END IF;
                  END IF;
               END LOOP;
            EXCEPTION
               WHEN OTHERS
               THEN
                  DECLARE
                     ERROR_CODE   NUMBER         := SQLCODE;
                     error_msg    VARCHAR2 (512) := SQLERRM;
                  BEGIN
                     IF ERROR_CODE != 100
                     THEN                                     --no data found
                        null;
                     END IF;
                  END;
            END;
         END;

         v_data_counter := v_data_counter + 1;
         v_stop_details (v_data_counter) := v_stop_detail;
         EXIT WHEN v_data_counter >= p_route_data.stop_details.COUNT;
      END LOOP;

      IF v_unattach_exist = 0
      THEN
         DELETE FROM tms_stop_detail
               WHERE stop_id = v_stop_detail.stop_id
                 AND shipping_unit_id = constant_unattachpo;

         DELETE FROM tms_po_stop_detail
               WHERE shipping_unit_id = constant_unattachpo
                 AND stop_id = v_stop_detail.stop_id;
      END IF;

      v_data_counter := 0;

      --loop for po
      LOOP
         EXIT WHEN v_pos.FIRST IS NULL;
         v_po := v_pos (v_pos.NEXT (v_data_counter));

         UPDATE tms_po
            SET weight = v_po.weight,
                weight_uom = v_po.weight_uom,
                delete_flag = v_po.delete_flag,
                last_update = v_last_update
          WHERE truck_route_instance_id = v_instance_id
            AND stop_id = v_po.stop_id
            AND po_id = v_po.po_id;

         IF SQL%NOTFOUND
         THEN
            INSERT INTO tms_po
                        (stop_id, po_id, truck_route_instance_id,
                         weight, weight_uom, last_update
                        )
                 VALUES (v_po.stop_id, v_po.po_id, v_instance_id,
                         v_po.weight, v_po.weight_uom, v_last_update
                        );
         END IF;

         v_data_counter := v_data_counter + 1;
         EXIT WHEN v_data_counter >= p_route_data.stop_pos.COUNT;
      END LOOP;

      --loop for po_stop_detail
      v_data_counter := 0;

      LOOP
         EXIT WHEN v_po_stop_details.FIRST IS NULL;
         v_po_stop_detail :=
                  v_po_stop_details (v_po_stop_details.NEXT (v_data_counter));

         IF v_po_stop_detail.stop_detail_id < 0
         THEN
            BEGIN
               SELECT sd_new_id
                 INTO v_new_id
                 FROM tms_temp_stop_detail
                WHERE sd_old_id = v_po_stop_detail.stop_detail_id;

               v_po_stop_detail.stop_detail_id := v_new_id;
            EXCEPTION
               WHEN NO_DATA_FOUND
               THEN
                  NULL;
            END;
         END IF;

         UPDATE tms.tms_po_stop_detail
            SET delete_flag = v_po_stop_detail.delete_flag,
                last_update = v_last_update
          WHERE truck_route_instance_id = v_instance_id
            AND stop_id = v_po_stop_detail.stop_id
            AND stop_detail_id = v_po_stop_detail.stop_detail_id
            AND po_id = v_po_stop_detail.po_id;

         IF SQL%NOTFOUND
         THEN
            INSERT INTO tms.tms_po_stop_detail
                        (stop_detail_id,
                         po_id, truck_route_instance_id,
                         stop_id,
                         shipping_unit_id,
                         last_update
                        )
                 VALUES (v_po_stop_detail.stop_detail_id,
                         v_po_stop_detail.po_id, v_instance_id,
                         v_po_stop_detail.stop_id,
                         (SELECT shipping_unit_id
                            FROM tms_stop_detail
                           WHERE ROWNUM <= 1
                             AND stop_detail_id =
                                               v_po_stop_detail.stop_detail_id),
                         v_last_update
                        );
         END IF;

         v_data_counter := v_data_counter + 1;
         v_po_stop_details (v_data_counter) := v_po_stop_detail;
         EXIT WHEN v_data_counter >= p_route_data.po_stop_details.COUNT;
      END LOOP;

      --put the information into the objects to return.
      FOR x IN (SELECT sd_old_id, sd_new_id
                  FROM tms_temp_stop_detail)
      LOOP
         IF NOT v_isfirst
         THEN
            tc_idmap.EXTEND;
         END IF;

         v_isfirst := FALSE;
         tc_idmap (tc_idmap.LAST) :=
                                    NEW id_relation (x.sd_old_id, x.sd_new_id);
      END LOOP;

      DELETE FROM tms_temp_stop_detail;

      --end the return;
      IF p_is_end_of_day = 1 OR p_is_end_of_day = 2
      THEN
         UPDATE tms_route_header h
            SET end_of_day = p_dt_eod,
                completion_program_name = 'BGL'
          WHERE h.truck_route_instance_id = v_instance_id
            AND NOT EXISTS (
                   SELECT 0
                     FROM tms_route_stop s
                    WHERE h.truck_route_instance_id =
                                                     s.truck_route_instance_id
                      AND (   s.status IS NULL
                           OR s.status NOT IN ('COMPLETE', 'EXCEPT')
                          ));

         IF SQL%NOTFOUND
         THEN
            IF p_is_end_of_day = 2
            THEN
               UPDATE tms_route_header h
                  SET end_of_day = p_dt_eod
                WHERE h.truck_route_instance_id = v_instance_id;
            ELSE
             null;
               RAISE miss_route_status;
            END IF;
         END IF;
      END IF;

      t_idupdate := NEW id_update (NULL, tc_idmap);
      COMMIT;
      RETURN t_idupdate;
   EXCEPTION
      WHEN miss_route_status
      THEN
         DECLARE
            v_stops     VARCHAR2 (500);
            v_exist     INTEGER;

            CURSOR stops_cur
            IS
               SELECT stop_id
                 FROM tms_route_stop
                WHERE truck_route_instance_id = v_instance_id
                  AND status IS NULL;

            v_stop_id   NUMBER (12);
         BEGIN
            OPEN stops_cur;

            LOOP
               FETCH stops_cur
                INTO v_stop_id;

               EXIT WHEN stops_cur%NOTFOUND;
               v_stops := v_stops || TO_CHAR (v_stop_id) || ',';
            END LOOP;

            CLOSE stops_cur;

            IF v_stops IS NOT NULL
            THEN
               SELECT INSTR (v_stops, ',', LENGTH (v_stops) - 1, 1)
                 INTO v_exist
                 FROM DUAL;

               IF v_exist != 0
               THEN
                  --that means the string is not end with ',' . we removed it.
                  SELECT SUBSTR (v_stops, 1, LENGTH (v_stops) - 1)
                    INTO v_stops
                    FROM DUAL;
               END IF;
            END IF;

            raise_application_error (-20002,
                                        'Stops are not existed in **'
                                     || v_stops
                                     || '$$'
                                    );
         END;
      WHEN OTHERS
      THEN
         ROLLBACK;

         --Record the exception data into that entity for -2292 only.
         DECLARE
            ERROR_CODE   NUMBER         := SQLCODE;
            error_msg    VARCHAR2 (512) := SQLERRM;
         BEGIN
          null;
            raise_application_error (-20006,
                                     TO_CHAR (ERROR_CODE) || error_msg);
            RETURN NULL;
         END;
   END;

   FUNCTION route_update_eod_ex (
      p_route_data      IN       route_data_ex,
      p_is_end_of_day   IN       INTEGER,
      p_dt_eod          IN       DATE,
      p_device_id                VARCHAR2,
      o_req_result      OUT      reqresult
   )
      RETURN id_update
   AS
---------------------------------------------*Declare some variable*---------------------------------------------------------
      constant_unattachpo   CHAR (14)                     := 'Unattached POs';
      v_route_stops         route_stops;
      v_stop_details        stop_details_ex;
      v_pos                 pos;
      v_po_stop_details     po_stop_details;
      v_route_stop          route_stop;
      v_stop_detail         stop_detail_ex;
      v_po_stop_detail      po_stop_detail;
      v_po                  po;
      v_last_update         DATE                                  := SYSDATE;
      v_eod                 DATE;
      v_instance_id         INTEGER                               := 0;
      v_data_counter        INTEGER                               := 0;
      v_isfirst             BOOLEAN                               := TRUE;
      v_new_id              INTEGER;
      v_unattach_exist      INTEGER                               := 0;
      t_idupdate            id_update;
      tc_idmap              id_map                       := NEW id_map (NULL);
      t_idrelation          id_relation;
      v_location_id         tms.tms_route_stop.location_id%TYPE;
      v_count               NUMBER;
      v_pallet_count        NUMBER;
      v_num                 NUMBER                                := 0;
      v_counterr            NUMBER (4);
      v_alreadyrun          NUMBER                                := 0;
      miss_route_status     EXCEPTION;
      v_miss_stp            INTEGER;
      v_cntempty            INTEGER                               := 0;
      v_cntsd               INTEGER                               := 0;
--------------------------------------------------*End declare*---------------------------------------------------------------
   BEGIN
      --get object to local variable.
      --v_route_data := p_route_data;
      v_route_stops := p_route_data.route_stops;
      v_stop_details := p_route_data.stop_details;
      v_po_stop_details := p_route_data.po_stop_details;
      v_pos := p_route_data.stop_pos;

      --This if for initialize the empty collections, so we do not need initialize it later.
      IF v_route_stops IS NULL
      THEN
         --  ex_route_stops := NEW route_stops (NULL);
         v_route_stops := NEW route_stops (NULL);
      END IF;

      IF v_pos IS NULL
      THEN
         -- ex_pos := NEW pos (NULL);
         v_pos := NEW pos (NULL);
      END IF;

      IF v_stop_details IS NULL
      THEN
         -- ex_stop_details := NEW stop_details (NULL);
         v_stop_details := NEW stop_details_ex (NULL);
      END IF;

      IF v_po_stop_details IS NULL
      THEN
         --  ex_po_stop_details := NEW po_stop_details (NULL);
         v_po_stop_details := NEW po_stop_details (NULL);
      END IF;

------End initialize the empty collections
      v_instance_id := p_route_data.route_header.instance_id;

      --Insert into the log table when end of day, so we know they do this operation.
      IF p_is_end_of_day = 1
      THEN
         INSERT INTO tms_handheld_log
              VALUES (SUBSTR (p_device_id, 1, 20), SYSDATE, 0,
                      'BGL-ENDOFDAY', TO_CHAR (v_instance_id), SYSDATE,
                      tms_handheld_seq.NEXTVAL);
      END IF;

      UPDATE tms_route_header
         SET last_update = v_last_update
       WHERE truck_route_instance_id = v_instance_id;

      --loop for route_stop
      LOOP
         EXIT WHEN v_route_stops.FIRST IS NULL;
         v_route_stop := v_route_stops (v_route_stops.NEXT (v_data_counter));

         UPDATE tms_route_stop
            SET actual_arrival_dt = v_route_stop.actual_arrival,
                enroute_time = v_route_stop.enroute_dt,
                actual_departure_dt = v_route_stop.actual_departure,
                special_instructions = v_route_stop.special_instructions,
                exception_code = v_route_stop.exception_code,
                exception_comments = v_route_stop.exception_comments,
                status =
                   DECODE (v_route_stop.status,
                           NULL, 'OPEN',
                           v_route_stop.status
                          ),
                last_update = v_last_update
          WHERE truck_route_instance_id = v_instance_id
            AND stop_id = v_route_stop.stop_id;

         IF v_stop_details.COUNT = 0
         --If we do not upload every thing ,we erase the unattachedPo.
         THEN
            DELETE FROM tms_stop_detail
                  WHERE stop_id = v_route_stop.stop_id
                    AND shipping_unit_id = constant_unattachpo;

            DELETE FROM tms_po_stop_detail
                  WHERE shipping_unit_id = constant_unattachpo
                    AND stop_id = v_route_stop.stop_id;
         END IF;

         v_data_counter := v_data_counter + 1;
         EXIT WHEN v_data_counter >= p_route_data.route_stops.COUNT;
      END LOOP;

      --loop for stop_detail
      v_unattach_exist := 0;
      v_data_counter := 0;

      LOOP
         EXIT WHEN v_stop_details.FIRST IS NULL;
         v_stop_detail :=
                        v_stop_details (v_stop_details.NEXT (v_data_counter));

         IF     v_stop_detail.scan_timestamp IS NULL
            AND v_stop_detail.line_status = 'E'
         THEN
            v_stop_detail.scan_timestamp := SYSDATE;
         END IF;

         UPDATE tms_stop_detail
            SET shipping_unit_id = v_stop_detail.scan_id,
                intf_status =
                   DECODE (v_stop_detail.scan_timestamp,
                           NULL, intf_status,
                           scan_dt, intf_status,
                           'READY'
                          ),
                status = v_stop_detail.line_status,
                scan_flag = v_stop_detail.scan_ind,
                scan_dt = v_stop_detail.scan_timestamp,
                description = v_stop_detail.description,
                weight = v_stop_detail.weight,
                weight_uom = v_stop_detail.weight_uom,
                exception_code = v_stop_detail.exception_code,
                exception_comment = v_stop_detail.exception_comment,
                --v_stop_detail.exception_comment,
                package_type = v_stop_detail.package_type,
                last_update = v_last_update,
                container_id = v_stop_detail.container_id
          --when the exceptionCode is null,we set the value to the column.
         WHERE  truck_route_instance_id = v_instance_id
            AND stop_id = v_stop_detail.stop_id
            AND shipping_unit_id = v_stop_detail.scan_id
            AND task_type != 'DROP'
            AND task_type =
                   DECODE (v_stop_detail.pick_up_drop_off_ind,
                           'D', 'DROP',
                           'P', 'PICK',
                           'E', 'EMPT',
                           'L', 'LOAD',
                           'ERR'
                          );

         v_cntsd := SQL%ROWCOUNT;

         IF v_cntsd = 0
         THEN
            UPDATE tms_stop_detail
               SET shipping_unit_id = v_stop_detail.scan_id,
                   intf_status =
                      DECODE (v_stop_detail.scan_timestamp,
                              NULL, intf_status,
                              scan_dt, intf_status,
                              'READY'
                             ),
                   status = v_stop_detail.line_status,
                   scan_flag = v_stop_detail.scan_ind,
                   stop_id = v_stop_detail.stop_id,
                   scan_dt = v_stop_detail.scan_timestamp,
                   description = v_stop_detail.description,
                   weight = v_stop_detail.weight,
                   weight_uom = v_stop_detail.weight_uom,
                   exception_code = v_stop_detail.exception_code,
                   exception_comment = v_stop_detail.exception_comment,
                   package_type = v_stop_detail.package_type,
                   last_update = v_last_update,
                   container_id = v_stop_detail.container_id
             WHERE truck_route_instance_id = v_instance_id
               AND shipping_unit_id = v_stop_detail.scan_id
               AND task_type = 'DROP'
               AND task_type =
                      DECODE (v_stop_detail.pick_up_drop_off_ind,
                              'D', 'DROP',
                              'P', 'PICK',
                              'E', 'EMPT',
                              'L', 'LOAD',
                              'ERR'
                             );

            v_cntsd := SQL%ROWCOUNT;
         END IF;

         IF v_cntsd = 0
         THEN
            IF v_stop_detail.scan_id = constant_unattachpo
            THEN
               v_unattach_exist := 2;
            END IF;

            SELECT tms.tms_bgl_route_stop_detail_seq.NEXTVAL
              INTO v_new_id
              FROM DUAL;

            INSERT INTO tms_temp_stop_detail
                 VALUES (v_new_id, v_stop_detail.stop_detail_id);

            v_stop_detail.stop_detail_id := v_new_id;

            INSERT INTO tms_stop_detail
                        (stop_detail_id, truck_route_instance_id,
                         stop_id, destination_id, trailer_id,
                         task_type,
                         shipping_unit_id, description,
                         package_type,
                         weight,
                         weight_uom, host_created_dt,
                         status,
                         exception_code,
                         scan_flag,
                         scan_dt, last_update,
                         exception_comment,
                         container_id, intf_status
                        )
                 VALUES (v_stop_detail.stop_detail_id, v_instance_id,
                         v_stop_detail.stop_id, 0, '',
                         DECODE (v_stop_detail.pick_up_drop_off_ind,
                                 'D', 'DROP',
                                 'P', 'PICK',
                                 'E', 'EMPT',
                                 'L', 'LOAD',
                                 'ERR'
                                ),
                         v_stop_detail.scan_id, v_stop_detail.description,
                         v_stop_detail.package_type,
                         NVL (v_stop_detail.weight, 0),
                         v_stop_detail.weight_uom, SYSDATE,
                         v_stop_detail.line_status,
                         v_stop_detail.exception_code,
                         v_stop_detail.scan_ind,
                         v_stop_detail.scan_timestamp, SYSDATE,
                         v_stop_detail.exception_comment,
                         v_stop_detail.container_id, 'READY'
                        );
         ELSE
            IF v_stop_detail.stop_detail_id < 0
            THEN
               --For some reason, the negative value is not updated in client and it's uploaded again,
               --the oracle side get the right value, we just make the value correct so po_stop_detail will not inserted wrong value.
               SELECT stop_detail_id
                 INTO v_new_id
                 FROM tms_stop_detail
                WHERE truck_route_instance_id = v_instance_id
                  AND stop_id = v_stop_detail.stop_id
                  AND shipping_unit_id = v_stop_detail.scan_id;

               /* This is not nesscary since the unique key is stop_id and scan_id.

               AND task_type =
                      DECODE (v_stop_detail.pick_up_drop_off_ind,
                              'D', 'DROP',
                              'P', 'PICK',
                              'E', 'EMPT',
                              'L', 'LOAD'
                             );
                    */
               INSERT INTO tms_temp_stop_detail
                    VALUES (v_new_id, v_stop_detail.stop_detail_id);
            --At this point , the temp table had the correct positive stop_detail_id that we can handle the
            --po_stop_detail properly.
            END IF;

            IF v_stop_detail.scan_id = constant_unattachpo
            THEN
               v_unattach_exist := 1;
            END IF;
         END IF;

         --if the error code has issue. We can record it into our object table.
         SELECT COUNT (stop_detail_id)
           INTO v_counterr
           FROM tms_stop_detail
          WHERE exception_code IS NULL
            AND status = 'E'
            AND stop_detail_id = v_stop_detail.stop_detail_id;

         IF v_counterr > 0 AND v_alreadyrun = 0
         THEN
            NULL;
             --if insert once, we will not insert for another loop;
             /*
             INSERT INTO tms_obj_route_data
                  VALUES (p_route_data.route_header, p_route_data.route_stops,
                          p_route_data.stop_pos, p_route_data.stop_details,
                          p_route_data.po_stop_details,
                          'Exception code can not be null when the status is E',
                          v_instance_id);
            */
            v_alreadyrun := 1;
         END IF;

         --generate the location code and the number of composite pallets which were dropped off
         BEGIN
            BEGIN
               SELECT   s.location_id, COUNT (*)
                   INTO v_location_id, v_count
                   FROM tms_stop_detail d, tms.tms_route_stop s
                  WHERE d.stop_id = s.stop_id
                    AND d.stop_id = v_stop_detail.stop_id
                    AND d.shipping_unit_id = v_stop_detail.scan_id
                    AND d.truck_route_instance_id = s.truck_route_instance_id
                    AND d.truck_route_instance_id = v_instance_id
                    AND composite_pallet (d.shipping_unit_id) = 1
                    AND d.task_type IN ('DROP')
                    AND d.status IN ('Y')
               GROUP BY d.task_type, s.location_id;

               SELECT COUNT (*)
                 INTO v_num
                 FROM tms_empty_pallet
                WHERE location_id = v_location_id;

               IF v_num = 0
               THEN
                  INSERT INTO tms_empty_pallet
                       VALUES (v_location_id, v_count);
               ELSE
                  UPDATE tms_empty_pallet
                     SET pallet_count = pallet_count + v_count
                   WHERE location_id = v_location_id;
               END IF;
            EXCEPTION
               WHEN OTHERS
               THEN
                  DECLARE
                     ERROR_CODE   NUMBER         := SQLCODE;
                     error_msg    VARCHAR2 (512) := SQLERRM;
                  BEGIN
                     IF ERROR_CODE != 100
                     THEN                                     --no data found
                        NULL;
                     /*
                        INSERT INTO tms_obj_route_data
                             VALUES (p_route_data.route_header,
                                     p_route_data.route_stops,
                                     p_route_data.stop_pos,
                                     p_route_data.stop_details,
                                     p_route_data.po_stop_details, error_msg,
                                     v_instance_id);
                                     */
                     END IF;
                  END;
            END;

            BEGIN
               v_num := 0;

               FOR inx IN (SELECT   s.location_id, d.status,
                                    d.exception_code, COUNT (*) count_num
                               FROM tms.tms_stop_detail d,
                                    tms.tms_route_stop s
                              WHERE d.stop_id = s.stop_id
                                AND d.stop_id = v_stop_detail.stop_id
                                AND d.shipping_unit_id = v_stop_detail.scan_id
                                AND d.truck_route_instance_id =
                                                     s.truck_route_instance_id
                                AND d.truck_route_instance_id = v_instance_id
                                AND d.task_type IN ('EMPT')
                                AND d.status IN ('Y', 'E')
                           GROUP BY s.location_id, d.status, d.exception_code
                           ORDER BY d.status DESC)
               LOOP
                  v_num := v_num + 1;

                  SELECT COUNT (*)
                    INTO v_count
                    --the number of composite pallets dropped off on this store
                  FROM   tms_stop_detail d, tms.tms_route_stop s
                   WHERE d.stop_id = s.stop_id
                     AND d.stop_id = v_stop_detail.stop_id
                     AND d.truck_route_instance_id = s.truck_route_instance_id
                     AND d.truck_route_instance_id = v_instance_id
                     AND composite_pallet (d.shipping_unit_id) = 1
                     AND d.task_type IN ('DROP')
                     AND d.status IN ('Y');

                  IF v_num = 1
                  THEN
                     IF inx.status = 'Y'
                     THEN
                        SELECT pallet_count
                          INTO v_pallet_count
                          FROM tms_empty_pallet
                         WHERE location_id = inx.location_id;

                        IF inx.count_num >= v_pallet_count
                        THEN
                           UPDATE tms_empty_pallet
                              SET pallet_count = v_count
                            WHERE location_id = inx.location_id;
                        ELSE
                           UPDATE tms_empty_pallet
                              SET pallet_count = pallet_count - inx.count_num
                            WHERE location_id = inx.location_id;
                        END IF;
                     ELSIF inx.status = 'E' AND inx.exception_code = 'MISS'
                     THEN
                        UPDATE tms_empty_pallet
                           SET pallet_count = v_count
                         WHERE location_id = inx.location_id;
                     END IF;
                  END IF;
               END LOOP;
            EXCEPTION
               WHEN OTHERS
               THEN
                  DECLARE
                     ERROR_CODE   NUMBER         := SQLCODE;
                     error_msg    VARCHAR2 (512) := SQLERRM;
                  BEGIN
                     IF ERROR_CODE != 100
                     THEN                                     --no data found
                        NULL;
                     /*
                        INSERT INTO tms_obj_route_data
                             VALUES (p_route_data.route_header,
                                     p_route_data.route_stops,
                                     p_route_data.stop_pos,
                                     p_route_data.stop_details,
                                     p_route_data.po_stop_details, error_msg,
                                     v_instance_id);
                                     */
                     END IF;
                  END;
            END;
         END;

         v_data_counter := v_data_counter + 1;
         v_stop_details (v_data_counter) := v_stop_detail;
         EXIT WHEN v_data_counter >= p_route_data.stop_details.COUNT;
      END LOOP;

      IF v_unattach_exist = 0
      THEN
         DELETE FROM tms_stop_detail
               WHERE stop_id = v_stop_detail.stop_id
                 AND shipping_unit_id = constant_unattachpo;

         DELETE FROM tms_po_stop_detail
               WHERE shipping_unit_id = constant_unattachpo
                 AND stop_id = v_stop_detail.stop_id;
      END IF;

      v_data_counter := 0;

      --loop for po
      LOOP
         EXIT WHEN v_pos.FIRST IS NULL;
         v_po := v_pos (v_pos.NEXT (v_data_counter));

         UPDATE tms_po
            SET weight = v_po.weight,
                weight_uom = v_po.weight_uom,
                delete_flag = v_po.delete_flag,
                last_update = v_last_update
          WHERE truck_route_instance_id = v_instance_id
            AND stop_id = v_po.stop_id
            AND po_id = v_po.po_id;

         IF SQL%NOTFOUND
         THEN
            INSERT INTO tms_po
                        (stop_id, po_id, truck_route_instance_id,
                         weight, weight_uom, last_update
                        )
                 VALUES (v_po.stop_id, v_po.po_id, v_instance_id,
                         v_po.weight, v_po.weight_uom, v_last_update
                        );
         END IF;

         v_data_counter := v_data_counter + 1;
         EXIT WHEN v_data_counter >= p_route_data.stop_pos.COUNT;
      END LOOP;

      --loop for po_stop_detail
      v_data_counter := 0;

      LOOP
         EXIT WHEN v_po_stop_details.FIRST IS NULL;
         v_po_stop_detail :=
                  v_po_stop_details (v_po_stop_details.NEXT (v_data_counter));

         IF v_po_stop_detail.stop_detail_id < 0
         THEN
            BEGIN
               SELECT sd_new_id
                 INTO v_new_id
                 FROM tms_temp_stop_detail
                WHERE sd_old_id = v_po_stop_detail.stop_detail_id;

               v_po_stop_detail.stop_detail_id := v_new_id;
            EXCEPTION
               WHEN NO_DATA_FOUND
               THEN
                  NULL;
            END;
         END IF;

         UPDATE tms.tms_po_stop_detail
            SET delete_flag = v_po_stop_detail.delete_flag,
                last_update = v_last_update
          WHERE truck_route_instance_id = v_instance_id
            AND stop_id = v_po_stop_detail.stop_id
            AND stop_detail_id = v_po_stop_detail.stop_detail_id
            AND po_id = v_po_stop_detail.po_id;

         IF SQL%NOTFOUND
         THEN
            INSERT INTO tms.tms_po_stop_detail
                        (stop_detail_id,
                         po_id, truck_route_instance_id,
                         stop_id,
                         shipping_unit_id,
                         last_update
                        )
                 VALUES (v_po_stop_detail.stop_detail_id,
                         v_po_stop_detail.po_id, v_instance_id,
                         v_po_stop_detail.stop_id,
                         (SELECT shipping_unit_id
                            FROM tms_stop_detail
                           WHERE ROWNUM <= 1
                             AND stop_detail_id =
                                               v_po_stop_detail.stop_detail_id),
                         v_last_update
                        );
         END IF;

         v_data_counter := v_data_counter + 1;
         v_po_stop_details (v_data_counter) := v_po_stop_detail;
         EXIT WHEN v_data_counter >= p_route_data.po_stop_details.COUNT;
      END LOOP;

      --put the information into the objects to return.
      FOR x IN (SELECT sd_old_id, sd_new_id
                  FROM tms_temp_stop_detail)
      LOOP
         IF NOT v_isfirst
         THEN
            tc_idmap.EXTEND;
         END IF;

         v_isfirst := FALSE;
         tc_idmap (tc_idmap.LAST) :=
                                    NEW id_relation (x.sd_old_id, x.sd_new_id);
      END LOOP;

--We really did not need to do this stuff. it's ON COMMIT PRESERVE ROWS
--      DELETE FROM tms_temp_stop_detail;

      --end the return;
      IF p_is_end_of_day = 1 OR p_is_end_of_day = 2
      THEN
         UPDATE tms_route_header h
            SET end_of_day = p_dt_eod,
                completed_by = p_route_data.route_header.completed_by,
                completion_program_name = 'BGL'
          WHERE h.truck_route_instance_id = v_instance_id
            AND NOT EXISTS (
                   SELECT 0
                     FROM tms_route_stop s
                    WHERE h.truck_route_instance_id =
                                                     s.truck_route_instance_id
                      AND (   s.status IS NULL
                           OR s.status NOT IN ('COMPLETE', 'EXCEPT')
                          ));

         IF SQL%NOTFOUND
         THEN
            IF p_is_end_of_day = 2
            THEN
               UPDATE tms_route_header h
                  SET end_of_day = p_dt_eod
                WHERE h.truck_route_instance_id = v_instance_id;
            ELSE
               NULL;
               /*
                  INSERT INTO tms_obj_route_data
                       VALUES (p_route_data.route_header,
                               p_route_data.route_stops, p_route_data.stop_pos,
                               p_route_data.stop_details,
                               p_route_data.po_stop_details, 'Without Eod',
                               v_instance_id);
                  */
               COMMIT;
               RAISE miss_route_status;
            END IF;
         END IF;
      END IF;

      t_idupdate := NEW id_update (NULL, tc_idmap);
      COMMIT;
      o_req_result := NEW reqresult (1, 0, 'Update successfully.', SYSDATE);
      --    o_REQ_RESULT:=new
      RETURN t_idupdate;
   EXCEPTION
      WHEN miss_route_status
      THEN
         DECLARE
            v_stops     VARCHAR2 (500);
            v_exist     INTEGER;

            CURSOR stops_cur
            IS
               SELECT stop_id
                 FROM tms_route_stop
                WHERE truck_route_instance_id = v_instance_id
                  AND status IS NULL;

            v_stop_id   NUMBER (12);
         BEGIN
            OPEN stops_cur;

            LOOP
               FETCH stops_cur
                INTO v_stop_id;

               EXIT WHEN stops_cur%NOTFOUND;
               v_stops := v_stops || TO_CHAR (v_stop_id) || ',';
            END LOOP;

            CLOSE stops_cur;

            IF v_stops IS NOT NULL
            THEN
               SELECT INSTR (v_stops, ',', LENGTH (v_stops) - 1, 1)
                 INTO v_exist
                 FROM DUAL;

               IF v_exist != 0
               THEN
                  --that means the string is not end with ',' . we removed it.
                  SELECT SUBSTR (v_stops, 1, LENGTH (v_stops) - 1)
                    INTO v_stops
                    FROM DUAL;
               END IF;
            END IF;

            o_req_result := NEW reqresult (0, -20008, v_stops, SYSDATE);
            RETURN NULL;
         --raise_application_error (-20002, 'Stops are not existed in **'||v_stops||'$$' );
         END;
      WHEN OTHERS
      THEN
         ROLLBACK;

         --Record the exception data into that entity for -2292 only.
         DECLARE
            ERROR_CODE   NUMBER         := SQLCODE;
            error_msg    VARCHAR2 (512) := SQLERRM;
            v_objcnt pls_integer;
         BEGIN
           select count(1) into v_objcnt from tms_obj_route_data where  instanceid_col =v_instance_id;
           if v_objcnt=0 then
               INSERT INTO tms_obj_route_data
                    VALUES (p_route_data.route_header, p_route_data.route_stops,
                            p_route_data.stop_pos, p_route_data.stop_details,
                            p_route_data.po_stop_details,null, error_msg,to_char(ERROR_CODE),sysdate,p_device_id,
                            v_instance_id);
               COMMIT;
               end if;
            o_req_result := NEW reqresult (0, SQLCODE, SQLERRM, SYSDATE);
            -- raise_application_error (-20006,to_char(ERROR_CODE)||ERROR_MSG);
            RETURN NULL;
         END;
   END;
END tms_ws;
/