# Selima Website Content Management System # AcctTrx.pm: The accounting transaction form checker. # Copyright (c) 2007-2018 imacat. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Author: imacat # First written: 2007-09-22 package Selima::Checker::AcctTrx; use 5.008; use strict; use warnings; use base qw(Selima::Checker); use Selima::Accounting; use Selima::CallForm; use Selima::ChkFunc; use Selima::FetchRec; use Selima::ShortCut; use Selima::DataVars qw($DBH :forms); use Selima::Checker::AcctRec; # new: Initialize the checker sub new : method { local ($_, %_); my ($class, $self); ($class, @_) = @_; $_[1] = "accttrx" if scalar(@_) < 2 || !defined $_[1]; $self = $class->SUPER::new(@_); # Regularize the form subtype $self->_trim("formsub") if !$self->_missing("formsub"); # Record the form subtype $self->{"subtype"} = $self->{"form"}->param("formsub"); return $self; } # _check_date: Check the date # Use the default date checker # _check_ord: Check the order # Use the default order checker # _check_recs: Check the records sub _check_recs : method { local ($_, %_); my ($self, $form, $error, $debtcount, $crdtcount); $self = $_[0]; $form = $self->{"form"}; # Check the subtype # Check if it exists $error = $self->_missing("formsub"); return $error if defined $error; # Check the option value return {"msg"=>N_("This form suptype is invalid. Please specify a proper user.")} unless $self->{"subtype"} =~ /^(?:expense|income|trans)$/; # A form to fill in a cash expense transaction if ($self->{"subtype"} eq "expense") { $crdtcount = 0; } else { # Find the last-used credit record for ( $_ = 0; defined $form->param("crdt$_" . "subj") && defined $form->param("crdt$_" . "summary") && defined $form->param("crdt$_" . "amount"); $_++) {}; if ($_ > 0) { for ( $_--; $_ >= 0 && $form->param("crdt$_" . "subj") eq "" && $form->param("crdt$_" . "summary") eq "" && $form->param("crdt$_" . "amount") eq ""; $_--) {}; } $crdtcount = $_ + 1; if ($crdtcount == 0) { return {"msg"=>N_("Please fill in the credit side of the accounting transaction.")} if $self->{"subtype"} eq "trans"; return {"msg"=>N_("Please fill in the accounting transaction content.")}; } } # A form to fill in a cash income transaction if ($self->{"subtype"} eq "income") { $debtcount = 0; } else { # Find the last-used debit record for ( $_ = 0; defined $form->param("debt$_" . "subj") && defined $form->param("debt$_" . "summary") && defined $form->param("debt$_" . "amount"); $_++) {}; if ($_ > 0) { for ( $_--; $_ >= 0 && $form->param("debt$_" . "subj") eq "" && $form->param("debt$_" . "summary") eq "" && $form->param("debt$_" . "amount") eq ""; $_--) {}; } $debtcount = $_ + 1; if ($debtcount == 0) { return {"msg"=>N_("Please fill in the debit side of the accounting transaction.")} if $self->{"subtype"} eq "trans"; return {"msg"=>N_("Please fill in the accounting transaction content.")}; } } # Check the debit records for ($_ = 0; $_ < $debtcount; $_++) { my ($subform, $checker, $error); # Regularize it $self->_trim("debt$_" . "subj"); $self->_trim("debt$_" . "summary"); $self->_trim("debt$_" . "amount"); # Skip if it is not filled next if $form->param("debt$_" . "subj") eq "" && $form->param("debt$_" . "summary") eq "" && $form->param("debt$_" . "amount") eq ""; # Check with the subform checker $subform = new CGI(""); $subform->param("trx", $self->{"sn"}) if $self->{"iscur"}; $subform->param("subj", $form->param("debt$_" . "subj")); $subform->param("summary", $form->param("debt$_" . "summary")); $subform->param("amount", $form->param("debt$_" . "amount")); $checker = new Selima::Checker::AcctRec($subform); $error = $checker->check("subj", "summary", "amount"); return $error if defined $error; $form->param("debt$_" . "subj", $subform->param("subj")); $form->param("debt$_" . "summary", $subform->param("summary")); $form->param("debt$_" . "amount", $subform->param("amount")); } # Check the credit records for ($_ = 0; $_ < $crdtcount; $_++) { my ($subform, $checker, $error); # Regularize it $self->_trim("crdt$_" . "subj"); $self->_trim("crdt$_" . "summary"); $self->_trim("crdt$_" . "amount"); # Skip if it is not filled next if $form->param("crdt$_" . "subj") eq "" && $form->param("crdt$_" . "summary") eq "" && $form->param("crdt$_" . "amount") eq ""; # Check with the subform checker $subform = new CGI(""); $subform->param("trx", $self->{"sn"}) if $self->{"iscur"}; $subform->param("subj", $form->param("crdt$_" . "subj")); $subform->param("summary", $form->param("crdt$_" . "summary")); $subform->param("amount", $form->param("crdt$_" . "amount")); $checker = new Selima::Checker::AcctRec($subform); $error = $checker->check("subj", "summary", "amount"); return $error if defined $error; $form->param("crdt$_" . "subj", $subform->param("subj")); $form->param("crdt$_" . "summary", $subform->param("summary")); $form->param("crdt$_" . "amount", $subform->param("amount")); } # Check the balance if ($self->{"subtype"} eq "trans") { my ($sumdebit, $sumcredit); for ($_ = 0, $sumdebit = 0; $_ < $debtcount; $_++) { # Skip if it is not filled next if $form->param("debt$_" . "amount") eq ""; $sumdebit += $form->param("debt$_" . "amount"); } for ($_ = 0, $sumcredit = 0; $_ < $crdtcount; $_++) { # Skip if it is not filled next if $form->param("crdt$_" . "amount") eq ""; $sumcredit += $form->param("crdt$_" . "amount"); } return {"msg"=>N_("The total amounts of the debit side and the credit side are not balanced (debit [_1], credit [_2]."), "margs"=>[$sumdebit, $sumcredit]} if $sumdebit != $sumcredit; } return; } # _check_note: Check the note sub _check_note : method { local ($_, %_); my ($self, $form, $error); $self = $_[0]; $form = $self->{"form"}; # Check if it exists $error = $self->_missing("note"); return $error if defined $error; # Regularize it $self->_trimtext("note"); # Skip if it is not filled $form->param("note", "") if $form->param("note") eq C_("Fill in the note here."); return if $form->param("note") eq ""; # Check the length return {"msg"=>N_("This note is too long. (Max. length [#,_1])"), "margs"=>[${$self->{"maxlens"}}{"note"}]} if length $form->param("note") > ${$self->{"maxlens"}}{"note"}; # OK return; } # _redir_cnvttrans: Convert to a transfer transaction sub _redir_cnvttrans : method { local ($_, %_); my ($self, $form, $sum); $self = $_[0]; $form = $self->{"form"}; # Skip if not requested return if $self->_missing("cnvttrans"); # Skip if the form subtype not supplied return if !defined $self->{"subtype"}; # Skip if it is not an cash expense/income transaction return if $self->{"subtype"} !~ /^(?:expense|income)$/; # Set to a transfer transaction $form->param("formsub", "trans"); # Set the other side # A form to fill in a cash expense transaction if ($self->{"subtype"} eq "expense") { $form->param("crdt0subj", acctsubj_sn(ACCTSUBJ_CASH)); $form->param("crdt0summary", undef); $sum = 0; foreach (grep /^debt\d+amount$/, $form->param) { $self->_trim($_); $_ = $form->param($_); s/NT\$ ?//; s/,//g; s/\.0+$//; $sum += $_ if /^\d+$/; } $form->param("crdt0amount", $sum); # A form to fill in a cash income transaction } elsif ($self->{"subtype"} eq "income") { $form->param("debt0subj", acctsubj_sn(ACCTSUBJ_CASH)); $form->param("debt0summary", undef); $sum = 0; foreach (grep /^crdt\d+amount$/, $form->param) { $self->_trim($_); $_ = $form->param($_); s/NT\$ ?//; s/,//g; s/\.0+$//; $sum += $_ if /^\d+$/; } $form->param("debt0amount", $sum); } # Show the form again success_redirect undef; } # _redir_selsubj: Suspend and move to the accounting subject selection form sub _redir_selsubj : method { local ($_, %_); my $self; $self = $_[0]; @_ = sort grep /^sel(?:debt|crdt)\d+subj$/, $self->{"form"}->param; # Skip if not requested return if @_ == 0; # Record the hit button $_[0] =~ /^sel((?:debt|crdt)\d+)subj$/; $self->{"form"}->param("caller_index", $1); call_form FORM_ACCTSUBJ, ["list=lastlv"], "import_selsubj"; } return 1;