■在庫の取り消しと受発注の取り消し
在庫は、
現在の在庫=期首の在庫-期中から現在の出庫+期中から現在の入庫
となることが知られている(っていうか、ちょっと考えれば分かる)
したがって、入庫のキャンセル(すなわち返品になるが)する場合は、入庫なら入庫数マイナス、出庫なら出庫数マイナスをすればできる。何日前の在庫を求めるのでも、その日にちの在庫数を持っていなくても、出庫数、入庫数が分かればもとまる。
受発注の取り消しの場合は、入庫・出庫のキャンセル+入金、出金のキャンセルがあるが、これは、出来ない場合がある。理由は、入金や出金のキャンセルは、銀行やカード会社で決済されてしまうと、それを取り消すことが出来ないからだ(決済前であれば、決済金額を変更すればいいだけなので可能だけど)。
この場合は、単純なキャンセルではなく、なにか、別業務を考えなければいけない。
■DTPのアンドゥ
DTPなどのアンドゥ(元に戻す)を実現する場合、2つの方法が考えられる
(1)操作ごとに関連するデータを全部保持し、スナップショットとして持っている
(2)操作履歴をとっておいて、逆操作を行う
(2)が、いままでの話の、入庫・出庫のキャンセルに相当する。
(1)の場合、データが大量になる。(2)の場合、逆操作をおこなっても、かならずしも、元のものと一致しない。では、(2)で元のものと一致しない操作というのは、どのような場合なのか?(さっきだと、決済があるときは戻らない)、一致しない場合は、どのような操作を考えればよいのか?
■どういうときに、取り消し可能なのか?
ちゃんと証明できないけど、以下のときに可能な気がする
(1)単位元の存在
これは、何もしない操作だと思う。ふつう
(2)逆元(逆操作)の存在
何もしない操作に戻る方法がある。
■DTPの操作で考える
DTPの操作は、こんなかんじ。
(1)切り取り
(2)貼り込み
(3)移動
(4)変換(ポイントからミリなど)
(5)設定(幅、高さ、フォント、色そのたもろもろ)
で、このとき、(1)切り取りの逆操作は、(2)貼り込みで、(2)の逆操作は(1)になる。
ただし注意したいのは、大きな丸の上に、小さなまるが重なっていたとき、
大きなまるを削除し、小さなまるの上に貼りこむと、小さなまるは隠れて見えなくなり、以前の絵とは違う。
このように、絵の場合は、重なり具合を考慮し、レイヤ番号を導入し、そのレイヤに貼りこむことになる
(1図形1レイヤにしておく)
(3)の移動は、基本的に、逆操作は存在する。
なぜなら、移動とは、コンピューター上、XYZ座標の加法、または減法である。そして、XYZは、実数または整数である。実数や整数における加法・減法は、群をなしている。群は
G1.結合法則
G2.単位元 0
G3.逆元
が、あるとき、群になる。このうち、今話題にしているのはG2、G3の性質だから、逆操作は存在することになる。
(4)の変換は、存在しないことも多い。
変換は、XYZ座標や色空間(RGB,CMYK)における単位系を変える為の四則演算だが、
XYZ座標を整数で表す場合、四則演算に関して、割り算は群をなさないし、RGB,CMYKなど、色空間の変換は、逆元以前に、1対1ではない(表現できない色というのがある)
なので、変換においてはなりたたない。
(5)設定も成立しない、というか、設定は1対1対応ではなく、以前の値が何であれ、この値にするという形である。つまり、設定された値から、元の値を推測することはできない。
とすると、切り取り貼り込み移動くらいしか、できない?
■逆元が成立しないものに関して
ここで、ある属性の置換というものを考える
replace("対象.属性項目",元の値,設定値);
この場合、"対象.属性項目"を設定値にするという操作だが、この逆操作は、
"対象.属性項目"をもとの値にする、すなわち
replace("対象.属性項目",設定値,元の値);
である。(4)、(5)に関しては、上記のように、
・設定したい値の項目の変更前の値をとっておいて
・replace関数に置き換えれば
・元に戻る
ということである。
■操作番号と位置を入れる
1回の操作において、複数の値をかえることになる。
そこで、操作一つ一つに、操作番号を導入し、かつ、複数並んでいる項目(文字列とか)もあるので、その場合、位置番号も入れる。そうすると、
ある操作をおこなったとき
その操作の位置の、元の値と、操作後の値を
replace(操作番号,"対象.属性項目.位置",元の値,設定値);
で残しておけば、(すべての値を保持しておかなくても)
一つ前の操作は
replace(一つ前の操作番号,"対象.属性項目.位置",設定値,元の値);
の処理を全部行えば、元に戻る・・
といえそうな気がする・・・
どーだろー(^^;)
P.S 社会的に絶対に可逆しない、決済のようなものが含まれている場合は、
replace(一つ前の操作番号,"対象.属性項目.位置",設定値,元の値);
をやっても、もとにはもどらないので、だめ。