понедельник, 13 апреля 2009 г.

Сторно журналов ГК. Продолжение

В продолжении темы сторнирования журналов ГК.

Постановка задачи.
Получить список "честных" журналов ГК за период.
Что значит честных?
Предположим у нас 5 журналов. И пятый журнал оказался ошибочным (не важно по какой причине). Мы его сторнировали. Т.е. появился шестой журнал. Пятый и шестой - взаимно гасят друг друга и нам более не интересны. А вот первые 4 - это и есть список честных журналов. Из него исключены сторнированные журналы и то, чем их сторнировали.
Как получить такой список?

По идее, нам нужны несторнированные журналы (accrual_rev_status IS NULL). Однако под такое условие попадает и последний шестой журнал, а он - лишний.

Можно добавить условие, что журналы не должы быть сторнирующими (reversed_je_header_id IS NULL). И для нашего примера с шестью журналами этого достаточно. Однако нельзя исключать ситуацию, когда пользователь ошибся выполняя операцию сторнирования и сторнировал не то что нужно. А потом, поняв ошибку, сделал сторно на сторно. Т.е. появился 7-й журнал. И он нам нужен! 5-й и 6-ой гасят друг друга, а 7-й - "настоящий" и он нам нужен.

Здесь сделаем допущение, что из связки 5-6-7 журналы, нам нужен последний - 7-й. Хотя можно было бы говорить и об исходном - 5-ом.

Т.к. сторно на сторно можно делать не единожды, то в общем случае получается такая картина. Если есть цепочка сторнирования: исходный журнал(1)->сторно(2)->сторно(3)->сторно(4)->сторно(5)->сторно(6)-сторно(7)-... то нас в ней интересует последний журнал, но только в том случае, если он нечетный в цепочке.

Результирующий список честных журналов за период получается как то так.


SELECT * /* Обычные несторнированные и несторнирующие журналы */
FROM gl_je_headers gjh
WHERE gjh.period_name = 'ЯНВ-2009'
AND gjh.accrual_rev_status IS NULL
AND gjh.reversed_je_header_id IS NULL
UNION ALL
SELECT * /* дополнительные сторнировочные журналы */
FROM gl_je_headers gjh
WHERE gjh.period_name = 'ЯНВ-2009'
AND gjh.accrual_rev_status IS NULL
AND gjh.reversed_je_header_id IS NOT NULL
AND MOD((SELECT COUNT(*)
FROM gl_je_headers gjh2
WHERE gjh.period_name = 'ЯНВ-2009'
START WITH gjh2.je_header_id = gjh.je_header_id
CONNECT BY gjh2.je_header_id = PRIOR gjh2.reversed_je_header_id)
,2) <> 0

Последнее, на что нужно обратить внимание, это период, в котором проводилось сторнирование. Если не критично чтобы сторнирование было в том же периоде, что и исходный журнал, то из последнего подзапроса можно убрать условие по периоду.

1 комментарий:

Shredder комментирует...

в последнем подзапросе специально ошибка gjh.period_name вместо gjh2.period_name ?