├── README.md ├── autoagreement.pm ├── autodata.pm ├── autoform.pm ├── autoinfopage.pm ├── automobile_api.pm ├── autopayment.pm ├── autosms.pm ├── css ├── autoform.css ├── tip-redsimple.css └── tip-yellowsimple.css ├── images ├── 1x1.png ├── app-helper.png ├── autoform_wait.gif ├── biometric_pass.png ├── pbar-gray-gray.png ├── pbar-gray-white.png ├── pbar-red-gray.png ├── pbar-red-red.png ├── pbar-red-white.png ├── pbar-white-gray.png ├── pbar-white-red.png ├── tip-redsimple_arrows.gif ├── tip-yellowsimple_arrows.gif ├── type_jpg.png ├── type_pdf.png ├── type_png.png ├── type_tiff.png └── type_unk.png ├── model ├── autodata_type_c.pm ├── autodata_type_c_spb.pm ├── autodata_type_checkdoc.pm ├── autodata_type_d.pm └── autodata_type_rinnuovo.pm ├── scripts ├── autoform_clean.pl ├── autoform_fox.pl ├── autoform_softban.pl └── autoform_softban_warn.pl └── templates ├── autoform.tt2 ├── autoform_address_check.tt2 ├── autoform_confirm.tt2 ├── autoform_docstatus.tt2 ├── autoform_edit.tt2 ├── autoform_finish.tt2 ├── autoform_info.tt2 ├── autoform_info_entry.tt2 ├── autoform_list.tt2 ├── autoform_pcode.tt2 ├── autoform_upload.tt2 └── js_elements.tt2 /README.md: -------------------------------------------------------------------------------- 1 | # autoform 2 | Flexible and stable appointment system 3 | -------------------------------------------------------------------------------- /autoagreement.pm: -------------------------------------------------------------------------------- 1 | package VCS::Site::autoagreement; 2 | use strict; 3 | use utf8; 4 | 5 | use Math::Random::Secure qw(irand); 6 | use Data::Dumper; 7 | 8 | sub new 9 | # ////////////////////////////////////////////////// 10 | { 11 | my ( $class, $pclass, $vars ) = @_; 12 | 13 | my $self = bless {}, $pclass; 14 | 15 | $self->{ 'VCS::Vars' } = $vars; 16 | 17 | return $self; 18 | } 19 | 20 | sub create_online_appointment 21 | # ////////////////////////////////////////////////// 22 | { 23 | my $self = shift; 24 | 25 | my $app_id = $self->{ af }->query( 'sel1', __LINE__, " 26 | SELECT CreatedApp FROM AutoToken WHERE Token = ?", $self->{ token } 27 | ); 28 | 29 | $self->{ af }->log( 30 | "autoinfo_remote", "удалённая запись после проверки документов", $app_id 31 | ); 32 | 33 | $self->{ af }->query( 'query', __LINE__, " 34 | UPDATE Appointments SET Status = 13, AppDate = now(), CenterID = 47 WHERE ID = ?", {}, $app_id 35 | ); 36 | 37 | $self->{ af }->query( 'query', __LINE__, " 38 | UPDATE AutoToken SET ServiceType = 3 WHERE Token = ?", {}, $self->{ token } 39 | ); 40 | } 41 | 42 | sub create_sms_agreements_if_need 43 | # ////////////////////////////////////////////////// 44 | { 45 | my $self = shift; 46 | 47 | my ( $token_id, $already ) = $self->{ af }->query( 'sel1', __LINE__, " 48 | SELECT AutoToken.ID, DocUploadedAgreements.ID FROM AutoToken 49 | LEFT JOIN DocUploadedAgreements ON AutoToken.ID = DocUploadedAgreements.Token 50 | WHERE AutoToken.Token = ?", $self->{ token } 51 | ); 52 | 53 | return if $already; 54 | 55 | my $now = $self->{ vars }->get_system->now_date(); 56 | 57 | $self->{ af }->query( 'query', __LINE__, " 58 | LOCK TABLES DocUploadedAgreements WRITE, Templates READ, PriceRate READ, PriceList READ" 59 | ); 60 | 61 | my $maxAgr = $self->{ af }->query( 'sel1', __LINE__, " 62 | SELECT MAX(Agreement) FROM DocUploadedAgreements WHERE AgrDate = ?", $now 63 | ); 64 | 65 | $maxAgr =~ /(\d{2})(\d{6})(\d{6})/; 66 | 67 | my $maxOrder = sprintf('%06d', ( $2 ? $2 + 1 : 1 ) ); 68 | 69 | $now =~ /(\d{2})(\d{2})\-(\d{2})\-(\d{2})/; 70 | 71 | my $agreementNo = "46$maxOrder$3$4$2"; 72 | 73 | my $template = $self->{ af }->query( 'sel1', __LINE__, " 74 | SELECT ID FROM Templates WHERE TDate <= curdate() AND isJur=0 AND CenterID=46 ORDER BY TDate DESC LIMIT 1" 75 | ); 76 | 77 | my $rate = $self->{ vars }->admfunc->getRate( $self->{ vars }, 'RUR', $now, 46 ); 78 | 79 | $self->{ af }->query( 'query', __LINE__, " 80 | INSERT INTO DocUploadedAgreements (Token, Agreement, RateID, Template, AgrDate) VALUES (?, ?, ?, ?, ?)", {}, 81 | $token_id, $agreementNo, $rate, $template, $now 82 | ); 83 | 84 | $self->{ af }->query( 'query', __LINE__, "UNLOCK TABLES" ); 85 | } 86 | 87 | sub get_sms_agreements 88 | # ////////////////////////////////////////////////// 89 | { 90 | my $self = shift; 91 | 92 | my $agreement = $self->{ af }->query( 'sel1', __LINE__, " 93 | SELECT Agreement FROM AutoToken 94 | JOIN DocUploadedAgreements ON AutoToken.ID = DocUploadedAgreements.Token 95 | WHERE AutoToken.Token = ?", $self->{ token } 96 | ); 97 | 98 | $agreement =~ s/^([0-9]{2})([0-9]{6})([0-9]{6})$/$1.$2.$3/; 99 | 100 | return $agreement; 101 | } 102 | 103 | sub create_online_agreement 104 | # ////////////////////////////////////////////////// 105 | { 106 | my $self = shift; 107 | 108 | $self->{ af }->query( 'query', __LINE__, " 109 | LOCK TABLES 110 | DocHistory WRITE, DocPack WRITE, DocPackInfo WRITE, DocPackList WRITE, 111 | DocPackOptional WRITE, UserLog WRITE, Templates WRITE, 112 | Appointments WRITE, AppData WRITE, DocRequest WRITE, DocComments WRITE, AutoRemote WRITE, 113 | AutoPayment READ, AutoToken READ, VisaTypes READ, PriceRate READ, PriceList READ" 114 | ); 115 | 116 | my $now = $self->{ vars }->get_system->now_date(); 117 | 118 | my $agreementNo = $self->{ vars }->admfunc->getAgrNumber( $self->{ vars }, 47, $now ); 119 | 120 | my $rate = $self->{ vars }->admfunc->getRate( $self->{ vars }, 'RUR', $now, 47 ); 121 | 122 | my ( $sms_price, undef ) = $self->{ af }->get_payment_price( "sms" ); 123 | 124 | my ( $service_fee, $count ) = $self->{ af }->get_payment_price( "service" ); 125 | 126 | my $app = $self->{ af }->query( 'selallkeys', __LINE__, " 127 | SELECT Appointments.ID as AppID, FoxAddress, FName, LName, MName, 128 | Appointments.VType, Appointments.ID, SMS, Phone, Mobile, PassNum, PassDate, 129 | PassWhom, Appointments.Address, AutoRemote.BankID, AutoRemote.PVC, 130 | AutoToken.EMail, AutoRemote.ID as AutoRemoteID 131 | FROM AutoToken 132 | JOIN Appointments ON AutoToken.CreatedApp = Appointments.ID 133 | JOIN AutoRemote ON Appointments.ID = AutoRemote.AppID 134 | WHERE Token = ?", $self->{ token } 135 | )->[0]; 136 | 137 | my $sms = $self->{ af }->query( 'sel1', __LINE__, " 138 | SELECT AutoPayment.ID FROM AutoPayment 139 | JOIN AutoToken ON AutoPayment.AutoID = AutoToken.CreatedApp 140 | WHERE Token = ? AND AutoPayment.`Type` = 'sms' AND PaymentStatus = 2", 141 | $self->{ token } 142 | ); 143 | 144 | $sms = ( $sms ? 1 : 0 ); 145 | 146 | my $dsum = ( $service_fee * $count ) + ( $sms ? $sms_price : 0 ); 147 | 148 | my $template = $self->{ af }->query( 'sel1', __LINE__, " 149 | SELECT ID FROM Templates WHERE TDate <= curdate() AND isJur=0 AND CenterID=47 ORDER BY TDate DESC LIMIT 1" 150 | ); 151 | 152 | $self->{ af }->query( 'query', __LINE__, " 153 | INSERT INTO DocPack ( 154 | LastUpdate, Cur, RateID, Address, FName, LName, MName, DSum, ADate, PDate, PStatus, Login, 155 | AgreementNo, PType, Urgent, VisaType, AppID, Shipping, SMS, Phone, DovDate, DovNum, Template, 156 | CenterID, Mobile, PassNum, PassDate, PassWhom, ShippingAddress, XeroxPage, AnketaSrv, PrintSrv, 157 | PhotoSrv, VIPSrv, InsSum, ServSum, ShipNum, SkipIns, Translate, PersonalNo, TShipSum, isNewDHL, 158 | ConcilPaymentDate, officeToReceive, ShippingPhone, InsData, NoReceived 159 | ) VALUES ( 160 | curdate(), 'RUR', ?, ?, ?, ?, ?, ?, now(), now(), 25, ?, ?, 2, 0, ?, ?, 0, ?, ?, ?, ?, ?, 47, 161 | ?, ?, ?, ?, ?, 0, 0, 0, 0, 0, 0, ?, ?, 0, 0, '', 0, 0, now(), ?, ?, 0, 0 162 | )", {}, 163 | $rate, $app->{ Address }, $app->{ FName }, $app->{ LName }, $app->{ MName }, $dsum, 'remote_script', 164 | $agreementNo, $app->{ VType }, $app->{ ID }, $sms, $app->{ Phone }, '0000-00-00', 0, $template, 165 | $app->{ Phone }, $app->{ PassNum }, $app->{ PassDate }, $app->{ PassWhom }, 'адрес ещё не указан', 166 | $service_fee, 0, 0, 0, $app->{ Mobile }, 167 | ); 168 | 169 | my $doc_id = $self->{ af }->query( 'sel1', __LINE__, "SELECT last_insert_id()") || 0; 170 | 171 | my @alph = split( //, '0123456789abcdefghigklmnopqrstuvwxyz' ); 172 | my $feedback_token = ""; 173 | $feedback_token .= $alph[ int( irand( 36 ) ) ] for ( 1..24 ); 174 | 175 | $self->{ af }->query( 'query', __LINE__, " 176 | INSERT INTO DocPackOptional (DocPackID, ShippingFree, Reject, FeedbackKey, SendInfoEmail) VALUES (?, 0, 0, ?, ?)", {}, 177 | $doc_id, $feedback_token, $app->{ EMail } 178 | ); 179 | 180 | $self->{ af }->query( 'query', __LINE__, " 181 | INSERT INTO DocComments (DocID, Login, CommentText, CommentDate) VALUES (?, ?, ?, now())", {}, 182 | $doc_id, 'remote_script', 'Договор сформирован автоматически системой удалённой подачи; договор был оплачен картой через платёжный шлюз' 183 | ); 184 | 185 | my $bankids = parse_complex_data( $self, $app->{ BankID } ); 186 | 187 | my $appdata = $self->{ af }->query( 'selallkeys', __LINE__, " 188 | SELECT ID, RFName, RMName, RLName, PassNum, BirthDate, AppSDate 189 | FROM AppData WHERE AppID = ? AND Status != 2", $app->{ AppID } 190 | ); 191 | 192 | my $docpackinfo = {}; 193 | 194 | for ( @$appdata ) { 195 | 196 | my $id = $bankids->{ $_->{ ID } } || " "; 197 | 198 | $docpackinfo->{ $id } = [] unless ref( $docpackinfo->{ $id } ) eq 'ARRAY'; 199 | 200 | push( @{ $docpackinfo->{ $id } }, $_ ); 201 | } 202 | 203 | for my $info_bankid ( keys %$docpackinfo ) { 204 | 205 | $self->{ af }->query( 'query', __LINE__, " 206 | INSERT INTO DocPackInfo (PackID, BankID, VisaCnt) VALUES (?, ?, ?)", {}, 207 | $doc_id, $info_bankid, scalar( @{ $docpackinfo->{ $info_bankid } } ) 208 | ); 209 | 210 | my $info_id = $self->{ af }->query( 'sel1', __LINE__, "SELECT last_insert_id()") || 0; 211 | 212 | for ( @{ $docpackinfo->{ $info_bankid } } ) { 213 | 214 | $self->{ af }->query( 'query', __LINE__, " 215 | INSERT INTO DocPackList ( 216 | PackInfoID, CBankID, FName, LName, MName, isChild, PassNum, SDate, Login, 217 | Status, ApplID, iNRes, Concil, MobileNums, ShipAddress, ShipNum, RTShipSum, 218 | FlyDate, ShipPhone, ShipMail, BthDate, AgeCatA 219 | ) VALUES ( 220 | ?, ?, ?, ?, ?, ?, ?, ?, now(), 25, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? 221 | )", {}, 222 | $info_id, $info_bankid, $_->{ RFName }, $_->{ RLName }, $_->{ RMName }, 0, 223 | $_->{ PassNum }, 'remote_script', $_->{ ID }, 0, 0, ' ', ' ', 0, 0, 224 | $_->{ AppSDate }, 0, 0, $_->{ BirthDate }, 0 225 | ); 226 | 227 | my $list_id = $self->{ af }->query( 'sel1', __LINE__, "SELECT last_insert_id()") || 0; 228 | 229 | $self->{ af }->query( 'query', __LINE__, " 230 | INSERT INTO DocRequest (PackListID, VisaDataNumberEntries, VisaDataPurposeTravel, 231 | VisaDataDuration, VisaDataMainDestination) 232 | VALUES (?, 'M', 'TU', '90', 'I')", {}, 233 | $list_id, 234 | ); 235 | 236 | my $secons_shift = 0; 237 | 238 | for my $sec ( 1, 2, 25 ) { 239 | 240 | $self->{ af }->query( 'query', __LINE__, " 241 | INSERT INTO DocHistory (DocID, PassNum, Login, HDate, StatusID, BankID) 242 | VALUES (?, ?, ?, DATE_ADD(now(), INTERVAL ? SECOND), ?, ?)", {}, 243 | $doc_id, $_->{ PassNum }, 'remote_script', $secons_shift, $sec, $info_bankid 244 | ); 245 | 246 | $secons_shift += 1; 247 | }; 248 | } 249 | } 250 | 251 | 252 | $self->{ af }->query( 'query', __LINE__, " 253 | UPDATE AutoRemote SET Agreement = ? WHERE ID = ?", {}, 254 | $doc_id, $app->{ AutoRemoteID } 255 | ); 256 | 257 | $self->{ af }->query( 'query', __LINE__, "UNLOCK TABLES" ); 258 | 259 | $agreementNo =~ s/^([0-9]{2})([0-9]{6})([0-9]{6})$/$1.$2.$3/; 260 | 261 | return $agreementNo; 262 | } 263 | 264 | sub parse_complex_data 265 | # ////////////////////////////////////////////////// 266 | { 267 | my ( $self, $data ) = @_; 268 | 269 | my @data_arr = split( /\|/, $data ); 270 | 271 | my $data = {}; 272 | 273 | for ( @data_arr ) { 274 | 275 | my @data_pair = split( /:/, $_ ); 276 | 277 | $data->{ $data_pair[0] } = $data_pair[1]; 278 | } 279 | 280 | return $data; 281 | } 282 | 283 | 1; -------------------------------------------------------------------------------- /automobile_api.pm: -------------------------------------------------------------------------------- 1 | package VCS::Site::automobile_api; 2 | use strict; 3 | 4 | use VCS::Vars; 5 | use VCS::Site::autodata; 6 | 7 | use Data::Dumper; 8 | use JSON; 9 | 10 | sub get_mobile_api 11 | # ////////////////////////////////////////////////// 12 | { 13 | my ( $self, $token ) = @_; 14 | 15 | my $vars = $self->{ 'VCS::Vars' }; 16 | 17 | my $table_id = $self->get_current_table_id(); 18 | 19 | my $api = $vars->getparam( 'mobile_api' ) || ''; 20 | 21 | return get_api_head( $self, 1 ) if $self->{ token } =~ /^\d\d$/; 22 | 23 | return get_values_for_api( $self ) if $api =~ /^get_appdata$/i; 24 | 25 | return set_values_from_api( $self ) if $api =~ /^set_appdata$/i; 26 | 27 | return get_api_centers( $self ) if $api =~ /^get_centers$/i; 28 | 29 | return get_doc_status( $self ) if $api =~ /^get_doc_status$/i; 30 | 31 | return get_advertisment() if $api =~ /^get_advertisment$/i; 32 | 33 | return get_push( $self, $1 ) if $api =~ /^push_(on|off)$/i; 34 | 35 | return get_api_head( $self, 2 ) if $api !~ /^get_token$/i; 36 | 37 | return get_api_head( $self, 0 ); 38 | } 39 | 40 | sub get_values_for_api 41 | # ////////////////////////////////////////////////// 42 | { 43 | my $self = shift; 44 | 45 | my $delete_fields = VCS::Site::autodata::get_mobile_api_fields( 'to_delete' ); 46 | 47 | my $tables_id = $self->get_current_table_id(); 48 | 49 | my $result = get_api_head( $self, 0 ); 50 | 51 | $result->{ data }->{ appointments } = $self->query( 'selallkeys', __LINE__, " 52 | SELECT * FROM AutoAppointments WHERE ID = ?", $tables_id->{ AutoAppointments } 53 | )->[0]; 54 | 55 | $result->{ data }->{ date } = $result->{ data }->{ appointments }->{ AppDate }; 56 | 57 | 58 | my ( $start, $end ) = $self->query( 'sel1', __LINE__, " 59 | SELECT TStart, TEnd FROM TimeData WHERE SlotID = ?", $result->{ data }->{ appointments }->{ TimeslotID } 60 | ); 61 | 62 | $_ = $self->{ vars }->get_system->time_to_str( $_ ) for ( $start, $end ); 63 | 64 | $result->{ data }->{ time } = "$start - $end"; 65 | 66 | $result->{ data }->{ center } = $self->query( 'sel1', __LINE__, " 67 | SELECT BName FROM Branches WHERE ID = ?", 68 | $result->{ data }->{ appointments }->{ CenterID } 69 | ); 70 | 71 | my ( $status, $appid ) = $self->query( 'sel1', __LINE__, " 72 | SELECT Finished, CreatedApp FROM AutoToken WHERE ID = ?", $tables_id->{ AutoToken } 73 | ); 74 | 75 | $result->{ data }->{ status } = ( $status ? 'finished' : 'ongoing' ); 76 | 77 | if ( $status) { 78 | 79 | my $appnum = $self->query( 'sel1', __LINE__, " 80 | SELECT AppNum FROM Appointments WHERE ID = ?", $appid 81 | ); 82 | 83 | $appnum =~ s!(\d{3})(\d{4})(\d{2})(\d{2})(\d{4})!$1/$2/$3/$4/$5!; 84 | 85 | $result->{ data }->{ appnum } = $appnum; 86 | } 87 | 88 | delete $result->{ data }->{ appointments }->{ $_ } for ( @{ $delete_fields->{ appointments } } ); 89 | 90 | my $all_applicants = $self->query( 'selallkeys', __LINE__, " 91 | SELECT * FROM AutoAppData WHERE AppID = ?", $tables_id->{ AutoAppointments } 92 | ); 93 | 94 | for my $app ( 0..$#$all_applicants ) { 95 | 96 | my $sch_app = {}; 97 | 98 | if ( $all_applicants->[ $app ]->{ SchengenAppDataID } != 0 ) { 99 | 100 | $sch_app = $self->query( 'selallkeys', __LINE__, " 101 | SELECT * FROM AutoSchengenAppData WHERE ID = ?", $all_applicants->[ $app ]->{ SchengenAppDataID } 102 | )->[0]; 103 | 104 | delete $sch_app->{ ID }; 105 | } 106 | 107 | $result->{ data }->{ schengen }->[ $app ] = $sch_app; 108 | 109 | delete $all_applicants->[ $app ]->{ $_ } for ( @{ $delete_fields->{ appdata } } ); 110 | 111 | $result->{ data }->{ appdata }->[ $app ] = $all_applicants->[ $app ]; 112 | } 113 | 114 | return $result; 115 | } 116 | 117 | sub set_values_from_api 118 | # ////////////////////////////////////////////////// 119 | { 120 | my $self = shift; 121 | 122 | my $enabled_fields_array = VCS::Site::autodata::get_mobile_api_fields(); 123 | 124 | my $vars = $self->{ 'VCS::Vars' }; 125 | 126 | my $json = $vars->getparam( 'data' ); 127 | 128 | my $data = decode_json( $json ); 129 | 130 | for my $table ( keys %{ $enabled_fields_array } ) { 131 | 132 | my %field_for_table = map { $_ => 1 } @{ $enabled_fields_array->{ $table } }; 133 | 134 | if ( $table =~ /^(appdata|schengen)$/ ) { 135 | 136 | for my $app ( @{ $data->{ $table } } ) { 137 | for my $field ( keys %{ $app } ) { 138 | delete $app->{ $field } unless exists $field_for_table{ $field }; 139 | } 140 | } 141 | } 142 | else { 143 | for my $field ( keys %{ $data->{ $table } } ) { 144 | delete $data->{ $table }->{ $field } unless exists $field_for_table{ $field }; 145 | } 146 | } 147 | } 148 | 149 | my $app_id = $self->insert_hash_table( 'AutoAppointments', $data->{ appointments } ); 150 | 151 | $self->query( 'query', __LINE__, " 152 | UPDATE AutoToken SET AutoAppID = ? WHERE Token = ?", {}, $app_id, $self->{ token } 153 | ); 154 | 155 | my $app_max = 0; 156 | 157 | for ( 0..$#{ $data->{ appdata } } ) { 158 | 159 | my $sch_id = $self->insert_hash_table( 'AutoSchengenAppData', $data->{ schengen }->[ $_ ] ); 160 | 161 | $data->{ appdata }->[ $_ ]->{ AppID } = $app_id; 162 | $data->{ appdata }->[ $_ ]->{ SchengenAppDataID } = $sch_id; 163 | 164 | $self->insert_hash_table( 'AutoAppData', $data->{ appdata }->[ $_ ] ); 165 | } 166 | 167 | $self->redirect( $self->{ token } . '&mobile_app=on' ); 168 | } 169 | 170 | sub get_api_centers 171 | # ////////////////////////////////////////////////// 172 | { 173 | my $self = shift; 174 | 175 | my $result = {}; 176 | 177 | my $all_centers = $self->query( 'selallkeys', __LINE__, " 178 | SELECT ID, BName, BAddr as address, phone, email, submissionTime, collectionTime 179 | FROM Branches 180 | WHERE isDeleted = 0 AND Display = 1" 181 | ); 182 | 183 | my $geo_data = VCS::Site::autodata::get_geo_branches(); 184 | 185 | for ( @$all_centers ) { 186 | 187 | $result->{ data }->{ $_->{ BName } } = $_; 188 | 189 | $result->{ data }->{ $_->{ BName } }->{ latitude } = $geo_data->{ $_->{ ID } }->[ 0 ]; 190 | 191 | $result->{ data }->{ $_->{ BName } }->{ longitude } = $geo_data->{ $_->{ ID } }->[ 1 ]; 192 | 193 | utf8::decode( $result->{ data }->{ $_->{ BName } }->{ address } ); 194 | 195 | delete $result->{ data }->{ $_->{ BName } }->{ BName }; 196 | } 197 | 198 | return $result; 199 | } 200 | 201 | sub get_doc_status 202 | # ////////////////////////////////////////////////// 203 | { 204 | my $self = shift; 205 | 206 | my $result = { 207 | 'data' => { 208 | 'status' => "0" 209 | } 210 | }; 211 | 212 | my $param = get_all_param( $self, 'docnum', 'birthdate' ); 213 | 214 | $result->{ data }->{ docnum } = $param->{ docnum }; 215 | 216 | return $result if !$param->{ docnum } or !$param->{ birthdate }; 217 | 218 | my $docid = $self->query( 'sel1', __LINE__, " 219 | SELECT ID FROM DocPack WHERE AgreementNo = ? AND PStatus != 7", 220 | $param->{ docnum } 221 | ) || 0; 222 | 223 | return $result unless $docid; 224 | 225 | return $result unless $param->{ birthdate } =~ /^([0-9]{2})([0-9]{2})([0-9]{4})$/; 226 | 227 | my $birthdate = "$3-$2-$1"; 228 | 229 | my $all_status = $self->query( 'selallkeys', __LINE__, " 230 | SELECT ApplID, Status, BthDate 231 | FROM DocPackInfo 232 | JOIN DocPackList ON DocPackInfo.ID = PackInfoID 233 | WHERE PackID = ?", $docid 234 | ); 235 | 236 | for ( @$all_status ) { 237 | 238 | $result->{ data }->{ status } = $_->{ Status } if $birthdate eq $_->{ BthDate }; 239 | } 240 | 241 | $result->{ data }->{ status } = "0" if $result->{ data }->{ status } == 7; 242 | 243 | $result->{ data }->{ status } = "3" if $result->{ data }->{ status } > 7; 244 | 245 | return $result; 246 | } 247 | 248 | sub get_advertisment 249 | # ////////////////////////////////////////////////// 250 | { 251 | return { data => [ '' ] }; 252 | } 253 | 254 | sub get_push 255 | # ////////////////////////////////////////////////// 256 | { 257 | my ( $self, $swich ) = @_; 258 | 259 | my $result = get_api_head( $self, 2, 'without_token' ); 260 | 261 | my $param = get_all_param( $self, 'docnum', 'mid', 'birthdate' ); 262 | 263 | return $result if !$param->{ docnum } or !$param->{ mid } or !$param->{ birthdate }; 264 | 265 | return $result unless $param->{ birthdate } =~ /^([0-9]{2})([0-9]{2})([0-9]{4})$/; 266 | 267 | my $birthdate = "$3-$2-$1"; 268 | 269 | my $docid = $self->query( 'sel1', __LINE__, " 270 | SELECT DocPack.ID 271 | FROM DocPack 272 | JOIN DocPackInfo ON DocPack.ID = DocPackInfo.PackID 273 | JOIN DocPackList On DocPackInfo.ID = DocPackList.PackInfoID 274 | WHERE AgreementNo = ? AND DocPackList.BthDate = ? AND PStatus != 7", 275 | $param->{ docnum }, $birthdate 276 | ); 277 | 278 | return get_api_head( $self, 3, 'without_token' ) unless $docid; 279 | 280 | $result = get_api_head( $self, 0, 'without_token' ); 281 | 282 | my ( $pushid, $pushstatus ) = $self->query( 'sel1', __LINE__, " 283 | SELECT ID, PushStatus FROM DocPackMobilePush WHERE DocPackID = ? AND MobileID = ?", 284 | $docid, $param->{ mid } 285 | ); 286 | 287 | if ( $swich =~ /on/i ) { 288 | 289 | $result->{ data }->{ push } = 'enabled'; 290 | 291 | if ( !$pushid ) { 292 | 293 | $self->query( 'query', __LINE__, " 294 | INSERT INTO DocPackMobilePush (DocPackID, PushStatus, MobileID) VALUES (?, 1, ?)", {}, 295 | $docid, $param->{ mid } 296 | ); 297 | } 298 | elsif ( $pushstatus != 1 ) { 299 | 300 | $self->query( 'query', __LINE__, " 301 | UPDATE DocPackMobilePush SET PushStatus = 1 WHERE ID = ?", {}, 302 | $pushid 303 | ); 304 | } 305 | } 306 | else { 307 | $result->{ data }->{ push } = 'disabled'; 308 | 309 | if ( $pushid and $pushstatus == 1 ) { 310 | 311 | $self->query( 'query', __LINE__, " 312 | UPDATE DocPackMobilePush SET PushStatus = 0 WHERE ID = ?", {}, 313 | $pushid 314 | ); 315 | } 316 | } 317 | 318 | return $result; 319 | } 320 | 321 | sub get_api_head 322 | # ////////////////////////////////////////////////// 323 | { 324 | my ( $self, $error_number, $without_token ) = @_; 325 | 326 | my $error_text = [ 327 | '', 328 | 'ошибка токена', 329 | 'ошибка API-запроса', 330 | 'договор не найден', 331 | 'у записи истёк срок действия', 332 | ]; 333 | 334 | my $result = { 335 | 'error' => { 336 | 'error' => $error_number, 337 | 'error_text' => $self->lang( $error_text->[ $error_number ] ), 338 | } 339 | }; 340 | 341 | $result->{ token } = $self->{ token } unless $without_token; 342 | 343 | return $result; 344 | } 345 | 346 | sub get_all_param 347 | # ////////////////////////////////////////////////// 348 | { 349 | my $self = shift; 350 | 351 | my $param = {}; 352 | 353 | for ( @_ ) { 354 | 355 | $param->{ $_ } = $self->{ vars }->getparam( $_ ) || ''; 356 | 357 | $param->{ $_ } =~ s/[^0-9]//g unless $_ eq 'mid'; 358 | } 359 | 360 | return $param; 361 | } 362 | 363 | 1; 364 | -------------------------------------------------------------------------------- /autopayment.pm: -------------------------------------------------------------------------------- 1 | package VCS::Site::autopayment; 2 | use strict; 3 | use utf8; 4 | 5 | use LWP::UserAgent; 6 | use HTTP::Request; 7 | use Crypt::OpenSSL::RSA; 8 | use Data::Dumper; 9 | use Date::Calc; 10 | use JSON; 11 | use Encode qw(decode encode); 12 | use MIME::Base64; 13 | 14 | sub new 15 | # ////////////////////////////////////////////////// 16 | { 17 | my ( $class, $pclass, $vars ) = @_; 18 | 19 | my $self = bless {}, $pclass; 20 | 21 | $self->{ 'VCS::Vars' } = $vars; 22 | 23 | return $self; 24 | } 25 | 26 | sub return_url 27 | # ////////////////////////////////////////////////// 28 | { 29 | 30 | my $self = shift; 31 | 32 | return decode( 'utf8', $self->{ autoform }->{ payment }->{ back_url } . $self->{ autoform }->{ paths }->{ addr } . '?t=' . $self->{ token } ); 33 | } 34 | 35 | sub payment 36 | # ////////////////////////////////////////////////// 37 | { 38 | 39 | my ( $self, $order_number, $amount, $type ) = @_; 40 | 41 | my $config = VCS::Site::autodata::get_settings(); 42 | 43 | my $amount_in_kopek = $amount * 100; 44 | 45 | my $data = { 46 | userName => $config->{ payment }->{ user_name }, 47 | password => $config->{ payment }->{ password }, 48 | orderNumber => $order_number, 49 | amount => $amount_in_kopek, 50 | returnUrl => return_url( $self ), 51 | }; 52 | 53 | my $response = LWP::UserAgent->new( timeout => 30 )->post( join( '/', $config->{ payment }->{ url } , 'register.do' ), $data ); 54 | 55 | return ( undef, undef ) unless $response->is_success; 56 | 57 | my $payment = JSON->new->pretty->decode( $response->decoded_content ); 58 | 59 | return ( $payment->{ orderId }, $payment->{ formUrl } ); 60 | } 61 | 62 | sub status 63 | # ////////////////////////////////////////////////// 64 | { 65 | 66 | my ( $self, $order_id, $type ) = @_; 67 | 68 | my $config = VCS::Site::autodata::get_settings(); 69 | 70 | my $data = { 71 | userName => $config->{ payment }->{ user_name }, 72 | password => $config->{ payment }->{ password }, 73 | orderId => $order_id, 74 | }; 75 | 76 | my $response = LWP::UserAgent->new(timeout => 30)->post( join( '/', $config->{ payment }->{ url }, 'getOrderStatus.do' ), $data ); 77 | 78 | return -1 unless $response->is_success; 79 | 80 | my $status = JSON->new->pretty->decode( $response->decoded_content ); 81 | 82 | $status->{ OrderStatus } =~ s/[^0-9]+//g; 83 | 84 | return $status->{ OrderStatus }; 85 | } 86 | 87 | sub cloud_payment 88 | # ////////////////////////////////////////////////// 89 | { 90 | 91 | my ( $self, $data ) = @_; 92 | 93 | my $config = VCS::Site::autodata::get_settings(); 94 | 95 | my $ua = LWP::UserAgent->new( timeout => 30 ); 96 | 97 | $ua->ssl_opts( 98 | SSL_cert_file => $config->{ cloud }->{ ssl_cert }, 99 | SSL_key_file => $config->{ cloud }->{ ssl_key }, 100 | SSL_passwd_cb => sub { return $config->{ cloud }->{ ssl_pwd }; } 101 | ); 102 | 103 | my $content = encode( 'utf8', JSON->new->pretty->encode( $data ) ); 104 | 105 | my $request = HTTP::Request->new( 'POST', $config->{ cloud }->{ url } ); 106 | 107 | $request->header('Content-Type' => 'application/json'); 108 | 109 | $request->header('X-Signature' => signature( $content ) ); 110 | 111 | $request->content( $content ); 112 | 113 | my $response = $ua->request( $request ); 114 | 115 | my $responses = { 116 | 201 => "OK", 117 | 401 => "ERROR: certificate", 118 | 409 => "ERROR: duplicate", 119 | 400 => "ERROR: validation", 120 | 503 => "ERROR: queue", 121 | }; 122 | 123 | my $response_line = $responses->{ $response->{ _rc } }; 124 | 125 | return ($response_line ? $response_line : "ERROR: unknown type (" . $response->{ _rc } . ")" ); 126 | } 127 | 128 | sub cloud_status 129 | # ////////////////////////////////////////////////// 130 | { 131 | 132 | my ( $self, $company, $docid ) = @_; 133 | 134 | my $config = VCS::Site::autodata::get_settings(); 135 | 136 | my $ua = LWP::UserAgent->new( timeout => 30 ); 137 | 138 | $ua->ssl_opts( 139 | SSL_cert_file => $config->{ cloud }->{ ssl_cert }, 140 | SSL_key_file => $config->{ cloud }->{ ssl_key }, 141 | SSL_passwd_cb => sub { return $config->{ cloud }->{ ssl_pwd }; } 142 | ); 143 | 144 | my $response = $ua->get( $config->{ cloud }->{ url } . "$company/status/$docid" ); 145 | 146 | return $response->{ _rc }; 147 | } 148 | 149 | sub signature 150 | # ////////////////////////////////////////////////// 151 | { 152 | my $data = shift; 153 | 154 | my $config = VCS::Site::autodata::get_settings(); 155 | 156 | open( my $file, '<', $config->{ cloud }->{ rsa_key } ) or return; 157 | 158 | my $key_string; 159 | 160 | $key_string .= $_ while <$file>; 161 | 162 | close $file; 163 | 164 | my $rsa = Crypt::OpenSSL::RSA->new_private_key( $key_string ); 165 | 166 | $rsa->use_pkcs1_padding(); 167 | 168 | $rsa->use_sha256_hash(); 169 | 170 | return encode_base64( $rsa->sign( $data ) ); 171 | } 172 | 173 | sub fox_pay_status_req 174 | # ////////////////////////////////////////////////// 175 | { 176 | my ( $self, $order_number ) = @_; 177 | 178 | my $config = VCS::Site::autodata::get_settings(); 179 | 180 | my $response = LWP::UserAgent->new( timeout => 30 )->get( $config->{ fox }->{ pay_status } . $order_number ); 181 | 182 | return 0 unless $response->is_success; 183 | 184 | my $result = decode( 'utf8', $response->{ _content } ); 185 | 186 | return ( $result =~ /Документ\s+$order_number\s+оплачен/i ? 1 : 0 ); 187 | } 188 | 189 | sub fox_pay_status 190 | # ////////////////////////////////////////////////// 191 | { 192 | my ( $self, $order_number_from, $order_number_to ) = @_; 193 | 194 | my $form_payment_ok = fox_pay_status_req( $self, $order_number_from ); 195 | 196 | my $to_payment_ok = fox_pay_status_req( $self, $order_number_to ); 197 | 198 | return $form_payment_ok && $to_payment_ok; 199 | } 200 | 201 | sub fox_pay_document 202 | # ////////////////////////////////////////////////// 203 | { 204 | my ( $self, $order_number ) = @_; 205 | 206 | my $config = VCS::Site::autodata::get_settings(); 207 | 208 | my $url_param = "login=" . $config->{ fox }->{ login } . "&password=" . $config->{ fox }->{ password } . 209 | "&documentType=order&number=" . $order_number . "&numberType=internalnumber&formName=Накладная"; 210 | 211 | my $response = LWP::UserAgent->new( timeout => 30 )->get( $config->{ fox }->{ document } . $url_param ); 212 | 213 | return "" unless $response->is_success; 214 | 215 | my $content = JSON->new->pretty->decode( $response->decoded_content ); 216 | 217 | my $document = $content->{ List }->[ 0 ]->{ BData }->[ 0 ]; 218 | 219 | return decode_base64($document) 220 | } 221 | 222 | sub fox_status 223 | # ////////////////////////////////////////////////// 224 | { 225 | my ( $self, $order_number_from, $order_number_to ) = @_; 226 | 227 | my $config = VCS::Site::autodata::get_settings(); 228 | 229 | my $url_param = "login=" . $config->{ fox }->{ login } . "&password=" . $config->{ fox }->{ password } . 230 | "&documentType=order&number=" . $order_number_from; 231 | 232 | my $response = LWP::UserAgent->new( timeout => 30 )->get( $config->{ fox }->{ track } . $url_param ); 233 | 234 | return "" unless $response->is_success; 235 | 236 | my $status = JSON->new->pretty->decode( $response->decoded_content ); 237 | 238 | my $line = ""; 239 | 240 | $line = $status->{ documents }->[ 0 ]->{ history }->[ -1 ]->{ eventState } 241 | if ( length( $status->{ documents }->[ 0 ]->{ history } ) > 0 ); 242 | 243 | return $line; 244 | } 245 | 246 | 1; -------------------------------------------------------------------------------- /autosms.pm: -------------------------------------------------------------------------------- 1 | package VCS::Site::autosms; 2 | use strict; 3 | use utf8; 4 | 5 | use Math::Random::Secure qw( irand ); 6 | use Digest::MD5 qw( md5_hex ); 7 | use Digest::SHA1 qw( sha1_hex ); 8 | use HTTP::Request::Common; 9 | use Data::Dumper; 10 | 11 | sub new 12 | # ////////////////////////////////////////////////// 13 | { 14 | my ( $class, $pclass, $vars ) = @_; 15 | 16 | my $self = bless {}, $pclass; 17 | 18 | $self->{ 'VCS::Vars' } = $vars; 19 | 20 | return $self; 21 | } 22 | 23 | sub get_phone_for_sms 24 | # ////////////////////////////////////////////////// 25 | { 26 | my ( $self, $without_app ) = @_; 27 | 28 | my $phone = undef; 29 | 30 | if ( $without_app ) { 31 | 32 | my ( $app_phone, $appdata_phone ) = $self->{ af }->query( 'sel1', __LINE__, " 33 | SELECT AutoAppointments.Phone, AutoAppData.AppPhone 34 | FROM AutoToken 35 | JOIN AutoAppointments ON AutoToken.AutoAppID = AutoAppointments.ID 36 | LEFT JOIN AutoAppData ON AutoToken.AutoAppDataID = AutoAppData.ID 37 | WHERE Token = ?", $self->{ token } 38 | ); 39 | 40 | $phone = ( !$appdata_phone ? $app_phone : $appdata_phone ); 41 | } 42 | else { 43 | $phone = $self->{ af }->query( 'sel1', __LINE__, " 44 | SELECT Phone FROM Appointments JOIN AutoToken ON Appointments.ID = AutoToken.CreatedApp 45 | WHERE AutoToken.Token = ?", $self->{ token } 46 | ); 47 | } 48 | 49 | return $phone; 50 | } 51 | 52 | sub get_code_from_db 53 | # ////////////////////////////////////////////////// 54 | { 55 | my ( $self, $without_app ) = @_; 56 | 57 | my ( $remote_id, $sms_code ) = ( 0, 0 ); 58 | 59 | if ( $without_app ) { 60 | 61 | ( $remote_id, $sms_code ) = $self->{ af }->query( 'sel1', __LINE__, " 62 | SELECT DocUploadedAgreements.ID, SMScode FROM DocUploadedAgreements 63 | JOIN AutoToken ON AutoToken.ID = DocUploadedAgreements.Token 64 | WHERE AutoToken.Token = ?", $self->{ token } 65 | ); 66 | } 67 | else { 68 | ( $remote_id, $sms_code ) = $self->{ af }->query( 'sel1', __LINE__, " 69 | SELECT AutoRemote.ID, SMScode FROM AutoRemote 70 | JOIN AutoToken ON AutoToken.CreatedApp = AutoRemote.AppID 71 | WHERE Token = ?", $self->{ token } 72 | ); 73 | } 74 | 75 | return ( $remote_id, $sms_code ); 76 | } 77 | 78 | sub get_code_for_sms 79 | # ////////////////////////////////////////////////// 80 | { 81 | my ( $self, $phone, $without_app ) = @_; 82 | 83 | my $config = VCS::Site::autodata::get_settings()->{ sms }; 84 | 85 | my ( $remote_id, $sms_code ) = get_code_from_db( $self, $without_app ); 86 | 87 | return md5_hex( $sms_code ) if $sms_code; 88 | 89 | my $new_code = int( irand( 9000 ) ) + 1000; 90 | 91 | my $sms_id = 0; 92 | 93 | $sms_id = sending_sms( $self, $phone, "Vash kod dogovora $new_code" ) unless $config->{ do_not_send_sms }; 94 | 95 | my $table = ( $without_app ? "DocUploadedAgreements" : "AutoRemote" ); 96 | 97 | $self->{ af }->query( 'query', __LINE__, " 98 | UPDATE $table SET SMScode = ?, SMSmsgID = ? WHERE ID = ?", {}, $new_code, $sms_id, $remote_id 99 | ); 100 | 101 | return md5_hex( $new_code ); 102 | } 103 | 104 | sub get_signed 105 | # ////////////////////////////////////////////////// 106 | { 107 | my $self = shift; 108 | 109 | my $sign_date = $self->query( 'sel1', __LINE__, " 110 | SELECT SMSsigned FROM DocUploadedAgreements 111 | JOIN AutoToken ON AutoToken.ID = DocUploadedAgreements.Token 112 | WHERE AutoToken.Token = ?", $self->{ token } 113 | ); 114 | 115 | return $sign_date; 116 | } 117 | 118 | sub code_from_sms_is_ok 119 | # ////////////////////////////////////////////////// 120 | { 121 | my ( $self, $code, $without_app ) = @_; 122 | 123 | my ( $remote_id, $sms_code ) = get_code_from_db( $self, $without_app ); 124 | 125 | return 0 unless $sms_code eq $code; 126 | 127 | my $table = ( $without_app ? "DocUploadedAgreements" : "AutoRemote" ); 128 | 129 | $self->{ af }->query( 'query', __LINE__, " 130 | UPDATE $table SET SMSsigned = now() WHERE ID = ?", {}, $remote_id 131 | ); 132 | 133 | 134 | return 1; 135 | } 136 | 137 | sub sending_sms 138 | # ////////////////////////////////////////////////// 139 | { 140 | my ( $self, $phone, $message ) = @_; 141 | 142 | my $sms = VCS::Site::autodata::get_settings()->{ sms }; 143 | 144 | my $sms_sign = join( ';', sort ( $sms->{ project }, $sms->{ sender }, $message, $phone ) ) . ';' . $sms->{ key }; 145 | 146 | $sms_sign = md5_hex( sha1_hex( $sms_sign ) ); 147 | 148 | my $ua = LWP::UserAgent->new; 149 | 150 | $ua->agent('Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686; en) Opera 7.60'); 151 | 152 | my $request_url = $sms->{ send_url } . '?project=' . $sms->{ project } . '&sender=' . $sms->{ sender } . 153 | '&message=' . $message . '&recipients=' . $phone . '&sign=' . $sms_sign; 154 | 155 | my $response = LWP::UserAgent->new( timeout => 30 )->get( $request_url ); 156 | 157 | return 0 unless $response->is_success; 158 | 159 | return 0 unless $response->content =~ /\"status\"\:\"success\"/; 160 | 161 | return 0 unless $response->content =~ /\"messages\_id\"\:\[([0-9]+)\]/; 162 | 163 | return $1; 164 | } 165 | 166 | 1; -------------------------------------------------------------------------------- /css/autoform.css: -------------------------------------------------------------------------------- 1 | 2 | .left{ 3 | text-align: left; 4 | } 5 | 6 | .center { 7 | text-align: center; 8 | } 9 | 10 | .centered { 11 | margin: 0 auto; 12 | } 13 | 14 | .bottom{ 15 | vertical-align: bottom; 16 | } 17 | 18 | .progressbar_gen{ 19 | display:none; 20 | border-collapse:collapse; 21 | width:100%; 22 | } 23 | 24 | .pr_size_gen{ 25 | background-size: 100% 100%; 26 | } 27 | 28 | .pr_red_red_gen{ background-image: url('/vcs/static/images/pbar-red-red.png'); } 29 | .pr_red_gray_gen{ background-image: url('/vcs/static/images/pbar-red-gray.png'); } 30 | .pr_red_white_gen{ background-image: url('/vcs/static/images/pbar-red-white.png'); } 31 | .pr_gray_gray_gen{ background-image: url('/vcs/static/images/pbar-gray-gray.png'); } 32 | .pr_gray_white_gen{ background-image: url('/vcs/static/images/pbar-gray-white.png'); } 33 | .pr_white_red_gen{ background-image: url('/vcs/static/images/pbar-white-red.png'); } 34 | .pr_white_gray_gen{ background-image: url('/vcs/static/images/pbar-white-gray.png'); } 35 | 36 | .pr_in_gen{ 37 | color:white; 38 | font-size:33px; 39 | line-height: 51px 40 | } 41 | 42 | .big_progr{ 43 | width:50px; 44 | height:50px; 45 | border-radius:25px; 46 | } 47 | 48 | .ltl_progr{ 49 | width:18px; 50 | height:18px; 51 | border-radius:9px; 52 | } 53 | 54 | .pr_past{ 55 | background:#FF6666; 56 | } 57 | 58 | .pr_current{ 59 | background:#CC0033; 60 | } 61 | 62 | .pr_future{ 63 | background:#999999; 64 | } 65 | 66 | .input_gen{ 67 | width:20em; 68 | } 69 | 70 | .exam_td_gen{ 71 | vertical-align:top; 72 | } 73 | 74 | .exam_span_gen{ 75 | color:gray; 76 | font-size:0.7em; 77 | } 78 | 79 | .stage_gen{ 80 | padding:5px; 81 | text-align:center; 82 | } 83 | 84 | .dotted_link{ 85 | color:#999999; 86 | font-size:12px; 87 | font-weight:normal; 88 | border-bottom:1px dotted #999999; 89 | text-decoration:none; 90 | } 91 | 92 | .dotted_link_middle{ 93 | color:#999999; 94 | font-weight:normal; 95 | border-bottom:1px dotted #999999; 96 | text-decoration:none; 97 | } 98 | 99 | .dotted_link_big{ 100 | color:#FF6666; 101 | font-weight:normal; 102 | border-bottom:1px dotted #DB121A; 103 | text-decoration:none; 104 | } 105 | 106 | .nfc_link{ 107 | text-decoration:none; 108 | color:#666666; 109 | } 110 | 111 | .optional_field{ 112 | background-color:#F5F5F5; 113 | border-width:1px; 114 | } 115 | 116 | .bold_text{ 117 | font-weight:bold; 118 | } 119 | 120 | .post_index{ 121 | font-size:14px; 122 | color:#FF6666; 123 | } 124 | 125 | .ltl_text{ 126 | font-size:12px; 127 | color:#999999; 128 | font-weight:normal; 129 | } 130 | 131 | .ltl_link{ 132 | font-size:12px; 133 | color:#999999; 134 | font-weight:normal; 135 | border-bottom: 1px dotted #999999; 136 | cursor:pointer; 137 | } 138 | 139 | .big_button{ 140 | width:100%; 141 | height:40px; 142 | margin-bottom:2px 143 | } 144 | 145 | .button_spacer{ 146 | margin-top:8px; 147 | } 148 | 149 | .finish_text_spacer{ 150 | margin-bottom:0px; 151 | margin-top:8px; 152 | } 153 | 154 | .small_button{ 155 | height:25px; 156 | } 157 | 158 | .info_list{ 159 | overflow:hidden; 160 | width:280px; 161 | max-width:280px; 162 | text-overflow:ellipsis; 163 | } 164 | 165 | .optional_line{ 166 | color:gray; 167 | } 168 | 169 | .m_right{ 170 | text-align:right; 171 | } 172 | 173 | .m_right_m{ 174 | text-align:right; 175 | white-space: nowrap; 176 | } 177 | 178 | .dashed_line{ 179 | border-bottom: 1px dashed #999999; 180 | } 181 | 182 | .width_full{ 183 | width:100%; 184 | } 185 | 186 | .width_small{ 187 | width:5%; 188 | } 189 | 190 | .margin_big{ 191 | margin:50px; 192 | } 193 | 194 | .yandex_map{ 195 | width:100%; 196 | height:400px; 197 | } 198 | 199 | .captcha_container { 200 | width:100%; 201 | } 202 | 203 | .g-recaptcha { 204 | transform-origin: left top; 205 | -webkit-transform-origin: left top; 206 | } 207 | 208 | .suppl_text { 209 | color:#585858; 210 | } 211 | 212 | .grayborder { 213 | border-collapse:collapse; 214 | border:1px solid #D3D3D3; 215 | padding:10px; 216 | } 217 | 218 | .biometric_box{ 219 | padding-top:10px; 220 | padding-bottom:5px; 221 | border-bottom-width:1px; 222 | border-bottom-color:red; 223 | border-bottom-style:solid; 224 | border-top-width:1px; 225 | border-top-color:red; 226 | border-top-style:solid; 227 | } 228 | 229 | .biometric_right { 230 | font-size:15px; 231 | color:#666666; 232 | padding:0px; 233 | display:inline-block; 234 | } 235 | 236 | .biometric_left { 237 | display:inline; 238 | height:37px; 239 | } 240 | 241 | .biometric_left_inner { 242 | height:37px; 243 | display:table-cell; 244 | vertical-align:middle; 245 | text-align:center; 246 | } 247 | 248 | .disclaimer { 249 | border:1px solid black; 250 | display:none; 251 | padding:15px; 252 | font-size:9px; 253 | text-align:justify; 254 | } 255 | 256 | .oferta { 257 | border:1px solid black; 258 | padding:15px; 259 | font-size:9px; 260 | text-align:justify; 261 | } 262 | 263 | .editFullOption { 264 | border:1px solid gray; 265 | padding:15px; 266 | font-size:12px; 267 | font-color:gray; 268 | text-align:justify; 269 | } 270 | .editFullBlock { 271 | border:1px solid black; 272 | display:none; 273 | padding:15px; 274 | font-size:12px; 275 | text-align:justify; 276 | } 277 | 278 | .no_border { 279 | border: none; 280 | border-spacing: 0; 281 | border-collanse: collapse; 282 | } 283 | 284 | .add_info_text{ 285 | font-size:11px; 286 | font-weight:normal; 287 | } 288 | 289 | .gray_line{ 290 | border: 1px solid #D3D3D3; 291 | } 292 | 293 | .hidden { 294 | display:none; 295 | } 296 | 297 | .pc_hide { 298 | display:none; 299 | height:40px; 300 | text-align:center; 301 | vertical-align:bottom; 302 | padding-bottom:3px; 303 | } 304 | 305 | .pc_hide_line { 306 | display:none; 307 | text-align:center; 308 | vertical-align:bottom; 309 | font-weight:bold; 310 | text-transform:uppercase; 311 | } 312 | 313 | .middle { 314 | vertical-align:middle; 315 | } 316 | 317 | .uplsuccess { 318 | color: green; 319 | font-size:25px; 320 | line-height: 0.8; 321 | } 322 | 323 | .nope_doc { 324 | color:gray; 325 | } 326 | 327 | .ok_doc { 328 | color:green; 329 | } 330 | 331 | .err_doc { 332 | color:red; 333 | font-weight:bold; 334 | } 335 | 336 | .insist_doc { 337 | color:blue; 338 | } 339 | 340 | .doc_support_comment { 341 | display:inline-block; 342 | margin-left:20px; 343 | padding:10px; 344 | border-collapse:collapse; 345 | background-color:#FFCCCC; 346 | font-size:11px; 347 | } 348 | 349 | .log_comment { 350 | display:inline-block; 351 | margin-left:20px; 352 | padding:10px; 353 | border-collapse:collapse; 354 | background-color:#CCCCCC; 355 | font-size:11px; 356 | } 357 | 358 | .doc_app_comment { 359 | display:inline-block; 360 | margin-left:20px; 361 | padding:10px; 362 | border-collapse:collapse; 363 | background-color:#6699FF; 364 | font-size:11px; 365 | } 366 | 367 | .show_comment { 368 | display:inline-block; 369 | margin-left:20px; 370 | color:red; 371 | font-weight:bold; 372 | cursor:pointer; 373 | } 374 | 375 | .show_replace_option { 376 | display:inline-block; 377 | margin-left:20px; 378 | } 379 | 380 | .show_other_option { 381 | display:inline-block; 382 | } 383 | 384 | .add_comment { 385 | display:inline-block; 386 | margin-left:20px; 387 | color:black; 388 | font-size:10px; 389 | } 390 | 391 | .add_comment_block { 392 | display:inline-block; 393 | margin-left:20; 394 | } 395 | 396 | .very_important { 397 | color:red; 398 | font-weight:bold; 399 | } 400 | 401 | .files_uploaded { 402 | font-size:12px; 403 | } -------------------------------------------------------------------------------- /css/tip-redsimple.css: -------------------------------------------------------------------------------- 1 | .tip-redsimple { 2 | z-index:1000; 3 | text-align:left; 4 | border:1px solid #CC0033; 5 | border-radius:4px; 6 | -moz-border-radius:4px; 7 | -webkit-border-radius:4px; 8 | padding:6px 8px; 9 | min-width:50px; 10 | max-width:300px; 11 | color:#FFFFFF; 12 | background-color:#CC0033; 13 | } 14 | .tip-redsimple .tip-inner { 15 | font:12px/16px arial,helvetica,sans-serif; 16 | line-height:1.2; 17 | } 18 | 19 | .tip-redsimple .tip-arrow-top { 20 | margin-top:-6px; 21 | margin-left:-5px; 22 | top:0; 23 | left:50%; 24 | width:9px; 25 | height:6px; 26 | background:url(tip-redsimple_arrows.gif) no-repeat; 27 | } 28 | .tip-redsimple .tip-arrow-right { 29 | margin-top:-4px; 30 | margin-left:0; 31 | top:50%; 32 | left:100%; 33 | width:6px; 34 | height:9px; 35 | background:url(tip-redsimple_arrows.gif) no-repeat -9px 0; 36 | } 37 | .tip-redsimple .tip-arrow-bottom { 38 | margin-top:0; 39 | margin-left:-5px; 40 | top:100%; 41 | left:50%; 42 | width:9px; 43 | height:6px; 44 | background:url(tip-redsimple_arrows.gif) no-repeat -18px 0; 45 | } 46 | .tip-redsimple .tip-arrow-left { 47 | margin-top:-4px; 48 | margin-left:-6px; 49 | top:50%; 50 | left:0; 51 | width:6px; 52 | height:9px; 53 | background:url(tip-redsimple_arrows.gif) no-repeat -27px 0; 54 | } -------------------------------------------------------------------------------- /css/tip-yellowsimple.css: -------------------------------------------------------------------------------- 1 | .tip-yellowsimple { 2 | z-index:1000; 3 | text-align:left; 4 | border:1px solid #c7bf93; 5 | border-radius:4px; 6 | -moz-border-radius:4px; 7 | -webkit-border-radius:4px; 8 | padding:6px 8px; 9 | min-width:50px; 10 | max-width:300px; 11 | color:#000; 12 | background-color:#fff9c9; 13 | } 14 | .tip-yellowsimple .tip-inner { 15 | font:12px/16px arial,helvetica,sans-serif; 16 | line-height:1.2; 17 | } 18 | 19 | .tip-yellowsimple .tip-arrow-top { 20 | margin-top:-6px; 21 | margin-left:-5px; 22 | top:0; 23 | left:50%; 24 | width:9px; 25 | height:6px; 26 | background:url(tip-yellowsimple_arrows.gif) no-repeat; 27 | } 28 | .tip-yellowsimple .tip-arrow-right { 29 | margin-top:-4px; 30 | margin-left:0; 31 | top:50%; 32 | left:100%; 33 | width:6px; 34 | height:9px; 35 | background:url(tip-yellowsimple_arrows.gif) no-repeat -9px 0; 36 | } 37 | .tip-yellowsimple .tip-arrow-bottom { 38 | margin-top:0; 39 | margin-left:-5px; 40 | top:100%; 41 | left:50%; 42 | width:9px; 43 | height:6px; 44 | background:url(tip-yellowsimple_arrows.gif) no-repeat -18px 0; 45 | } 46 | .tip-yellowsimple .tip-arrow-left { 47 | margin-top:-4px; 48 | margin-left:-6px; 49 | top:50%; 50 | left:0; 51 | width:6px; 52 | height:9px; 53 | background:url(tip-yellowsimple_arrows.gif) no-repeat -27px 0; 54 | } -------------------------------------------------------------------------------- /images/1x1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig1023/autoform/13110f916a90a6679e614cffe18b8c6a9958a073/images/1x1.png -------------------------------------------------------------------------------- /images/app-helper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig1023/autoform/13110f916a90a6679e614cffe18b8c6a9958a073/images/app-helper.png -------------------------------------------------------------------------------- /images/autoform_wait.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig1023/autoform/13110f916a90a6679e614cffe18b8c6a9958a073/images/autoform_wait.gif -------------------------------------------------------------------------------- /images/biometric_pass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig1023/autoform/13110f916a90a6679e614cffe18b8c6a9958a073/images/biometric_pass.png -------------------------------------------------------------------------------- /images/pbar-gray-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig1023/autoform/13110f916a90a6679e614cffe18b8c6a9958a073/images/pbar-gray-gray.png -------------------------------------------------------------------------------- /images/pbar-gray-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig1023/autoform/13110f916a90a6679e614cffe18b8c6a9958a073/images/pbar-gray-white.png -------------------------------------------------------------------------------- /images/pbar-red-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig1023/autoform/13110f916a90a6679e614cffe18b8c6a9958a073/images/pbar-red-gray.png -------------------------------------------------------------------------------- /images/pbar-red-red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig1023/autoform/13110f916a90a6679e614cffe18b8c6a9958a073/images/pbar-red-red.png -------------------------------------------------------------------------------- /images/pbar-red-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig1023/autoform/13110f916a90a6679e614cffe18b8c6a9958a073/images/pbar-red-white.png -------------------------------------------------------------------------------- /images/pbar-white-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig1023/autoform/13110f916a90a6679e614cffe18b8c6a9958a073/images/pbar-white-gray.png -------------------------------------------------------------------------------- /images/pbar-white-red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig1023/autoform/13110f916a90a6679e614cffe18b8c6a9958a073/images/pbar-white-red.png -------------------------------------------------------------------------------- /images/tip-redsimple_arrows.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig1023/autoform/13110f916a90a6679e614cffe18b8c6a9958a073/images/tip-redsimple_arrows.gif -------------------------------------------------------------------------------- /images/tip-yellowsimple_arrows.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig1023/autoform/13110f916a90a6679e614cffe18b8c6a9958a073/images/tip-yellowsimple_arrows.gif -------------------------------------------------------------------------------- /images/type_jpg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig1023/autoform/13110f916a90a6679e614cffe18b8c6a9958a073/images/type_jpg.png -------------------------------------------------------------------------------- /images/type_pdf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig1023/autoform/13110f916a90a6679e614cffe18b8c6a9958a073/images/type_pdf.png -------------------------------------------------------------------------------- /images/type_png.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig1023/autoform/13110f916a90a6679e614cffe18b8c6a9958a073/images/type_png.png -------------------------------------------------------------------------------- /images/type_tiff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig1023/autoform/13110f916a90a6679e614cffe18b8c6a9958a073/images/type_tiff.png -------------------------------------------------------------------------------- /images/type_unk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig1023/autoform/13110f916a90a6679e614cffe18b8c6a9958a073/images/type_unk.png -------------------------------------------------------------------------------- /model/autodata_type_d.pm: -------------------------------------------------------------------------------- 1 | package VCS::Site::autodata_type_d; 2 | use strict; 3 | 4 | sub get_progressline 5 | # ////////////////////////////////////////////////// 6 | { 7 | return [ '', 8 | { big => 1, name => 'Начало', }, 9 | { big => 0, name => 'Даты поездки', }, 10 | { big => 1, name => 'Заявители', }, 11 | { big => 0, name => 'Данные паспорта', }, 12 | { big => 0, name => 'Данные загранпаспорта', }, 13 | { big => 1, name => 'Оформление', }, 14 | { big => 0, name => 'Данные для договора', }, 15 | { big => 0, name => 'Выбор даты записи', }, 16 | { big => 0, name => 'Офис выдачи', }, 17 | { big => 0, name => 'Подтверждение', }, 18 | { big => 1, name => 'Готово!', }, 19 | ]; 20 | } 21 | 22 | sub get_content_rules_hash 23 | # ////////////////////////////////////////////////// 24 | { 25 | 26 | my $standart_date_check = 'zD^(([012]\d|3[01])\.((0\d)|(1[012]))\.(19\d\d|20[0-3]\d))$'; 27 | 28 | return { 29 | 30 | 'Начало записи' => [ 31 | { 32 | page_ord => 100, 33 | progress => 1, 34 | param => 1, 35 | goto_link => 'to_start', 36 | page_db_id => 300001, 37 | }, 38 | { 39 | type => 'select', 40 | name => 'center', 41 | label => 'Визовый центр', 42 | comment => 'Выберите визовый центр для подачи документов', 43 | check => 'zN', 44 | db => { 45 | table => 'Appointments', 46 | name => 'CenterID', 47 | }, 48 | param => '[centers_from_db]', 49 | uniq_code => 'onchange="update_nearest_date_free_date();"', 50 | first_elements => 'default_free, 1, 44, 41', 51 | special => 'cach_this_value', 52 | }, 53 | { 54 | type => 'select', 55 | name => 'vtype', 56 | label => 'Тип визы', 57 | comment => 'Выберите тип запрашиваемой визы', 58 | check => 'zN', 59 | db => { 60 | table => 'Appointments', 61 | name => 'VType', 62 | }, 63 | param => '[visas_from_db]', 64 | first_elements => '13', 65 | special => 'cach_this_value', 66 | }, 67 | { 68 | type => 'input', 69 | name => 'num_of_person', 70 | label => 'Количество заявителей', 71 | comment => 'Укажите количество человек, запрашивающих визу', 72 | example => '1', 73 | check => 'zN', 74 | uniq_code => 'onkeyup="update_nearest_date_free_date(1);"', 75 | check_logic => [ 76 | { 77 | condition => 'less_than', 78 | offset => '40', 79 | }, 80 | ], 81 | db => { 82 | table => 'Appointments', 83 | name => 'NCount', 84 | }, 85 | }, 86 | { 87 | type => 'free_line', 88 | }, 89 | { 90 | type => 'info', 91 | name => 'free_date', 92 | label => 'Ближайшая доступная дата', 93 | comment => 'Вы сможете выбрать удобную для Вас дату подачи документов во время оформления записи', 94 | special => 'nearest_date', 95 | }, 96 | { 97 | type => 'free_line', 98 | }, 99 | { 100 | type => 'input', 101 | name => 'email', 102 | label => 'Email', 103 | comment => 'Введите существующий адрес почты. На него будет выслано подтверждение записи в визовый центр. Пожалуйста, проверьте правильность каждой буквы/символа, из которых состоит адрес Вашей электронной почты', 104 | example => 'info@example.ru', 105 | check => 'zWN\@\-\_\.', 106 | check_logic => [ 107 | { 108 | condition => 'this_is_email', 109 | }, 110 | { 111 | condition => 'email_not_blocked', 112 | }, 113 | ], 114 | db => { 115 | table => 'Appointments', 116 | name => 'EMail', 117 | }, 118 | }, 119 | { 120 | type => 'input', 121 | name => 'emailcheck', 122 | label => 'Подтвердите email', 123 | comment => 'Обратите внимание, что адрес электронной почты необходимо вводить вручную, не копируя его из предыдущего поля. Это поможет Вам избежать ошибки и возможной отправки подтверждения Вашей записи не тому адресату. ', 124 | example => 'info@example.ru', 125 | check => 'zWN\@\-\_\.', 126 | check_logic => [ 127 | { 128 | condition => 'equal', 129 | table => 'Appointments', 130 | name => 'EMail', 131 | full_error => 'EMail не совпадает с подтверждением', 132 | }, 133 | ], 134 | db => { 135 | table => 'AutoToken', 136 | name => 'EMail', 137 | }, 138 | special => 'no_copypast', 139 | }, 140 | { 141 | type => 'free_line', 142 | }, 143 | { 144 | type => 'disclaimer', 145 | name => 'pers_info', 146 | label_for => 'я согласен с условиями обработки персональных данных визовым центром', 147 | comment => 'disclaimer_text', 148 | check => 'true', 149 | full_line => 1, 150 | db => { 151 | table => 'Appointments', 152 | name => 'PersonalDataPermission', 153 | transfer => 'nope', 154 | }, 155 | }, 156 | { 157 | type => 'checkbox', 158 | name => 'mobil_info', 159 | label_for => 'я уведомлён о том, что на территории Визового центра запрещается пользоваться электронными мобильными устройствами', 160 | check => 'true', 161 | full_line => 1, 162 | db => { 163 | table => 'Appointments', 164 | name => 'MobilPermission', 165 | transfer => 'nope', 166 | }, 167 | relation => {}, 168 | }, 169 | { 170 | type => 'include', 171 | place => 'out', 172 | template => 'vip_form.tt2', 173 | }, 174 | ], 175 | 176 | 'Даты поездки' => [ 177 | { 178 | page_ord => 200, 179 | progress => 2, 180 | collect_date => 1, 181 | page_db_id => 300002, 182 | }, 183 | { 184 | type => 'input', 185 | name => 's_date', 186 | label => 'Дата начала поездки', 187 | comment => 'Введите предполагаемую дату начала поездки', 188 | example => '31.12.1900', 189 | check => $standart_date_check, 190 | check_logic => [ 191 | { 192 | condition => 'now_or_later', 193 | offset => '[collect_date_offset]', 194 | }, 195 | { 196 | condition => 'now_or_earlier', 197 | offset => 180, 198 | equality_is_also_fail => 1, 199 | full_error => 'Действует ограничение на максимальную дату вылета: не более [offset] с текущей даты', 200 | }, 201 | ], 202 | db => { 203 | table => 'Appointments', 204 | name => 'SDate', 205 | }, 206 | special => 'datepicker, mask', 207 | minimal_date => 'current', 208 | }, 209 | { 210 | type => 'input', 211 | name => 'f_date', 212 | label => 'Дата окончания поездки', 213 | comment => 'Введите предполагаемую дату окончания поездки', 214 | example => '31.12.1900', 215 | check => $standart_date_check, 216 | check_logic => [ 217 | { 218 | condition => 'equal_or_later', 219 | table => 'Appointments', 220 | name => 'SDate', 221 | error => 'Дата начала поездки', 222 | }, 223 | ], 224 | db => { 225 | table => 'Appointments', 226 | name => 'FDate', 227 | }, 228 | special => 'datepicker, mask', 229 | minimal_date => 's_date', 230 | }, 231 | ], 232 | 233 | 'Список заявителей' => [ 234 | { 235 | page_ord => 300, 236 | progress => 3, 237 | goto_link => 'back_to_appdata', 238 | all_app_in_title => 1, 239 | replacer => '[list_of_applicants]', 240 | page_db_id => 300003, 241 | }, 242 | ], 243 | 244 | 'Данные паспорта' => [ 245 | { 246 | page_ord => 400, 247 | progress => 4, 248 | all_app_in_title => 1, 249 | param => 1, 250 | page_db_id => 300004, 251 | }, 252 | { 253 | type => 'select', 254 | name => 'сitizenship', 255 | label => 'Гражданство в настоящее время', 256 | comment => 'Если у вас два гражданства, то укажите гражданство по паспорту той страны, который подаёте на визу', 257 | example => 'The Russian Federation', 258 | check => 'zN', 259 | db => { 260 | table => 'AppData', 261 | name => 'Citizenship', 262 | }, 263 | param => '[citizenship_countries]', 264 | first_elements => '70', 265 | }, 266 | { 267 | type => 'free_line', 268 | }, 269 | { 270 | type => 'input', 271 | name => 'rulname', 272 | label => 'Фамилия', 273 | comment => 'Введите фамилию на русском языке так, как она указана во внутреннем паспорте', 274 | example => 'Петров', 275 | check => 'zWЁ\s\-', 276 | check_logic => [ 277 | { 278 | condition => 'english_only_for_not_rf_citizen', 279 | full_error => 'Для граждан РФ фамилию необходимо вводить на русском языке', 280 | }, 281 | ], 282 | db => { 283 | table => 'AppData', 284 | name => 'RLName', 285 | }, 286 | format => 'capitalized' 287 | }, 288 | { 289 | type => 'input', 290 | name => 'rufname', 291 | label => 'Имя', 292 | comment => 'Введите имя на русском языке так, как оно указано во внутреннем паспорте', 293 | example => 'Петр', 294 | check => 'zWЁ\s\-', 295 | check_logic => [ 296 | { 297 | condition => 'english_only_for_not_rf_citizen', 298 | full_error => 'Для граждан РФ имя необходимо вводить на русском языке', 299 | }, 300 | ], 301 | db => { 302 | table => 'AppData', 303 | name => 'RFName', 304 | }, 305 | format => 'capitalized' 306 | }, 307 | { 308 | type => 'input', 309 | name => 'rumname', 310 | label => 'Отчество', 311 | comment => 'Введите отчество на русском языке так, как оно указано во внутреннем паспорте', 312 | example => 'Петрович', 313 | check => 'WЁ\s\-', 314 | check_logic => [ 315 | { 316 | condition => 'english_only_for_not_rf_citizen', 317 | full_error => 'Для граждан РФ отч необходимо вводить на русском языке', 318 | }, 319 | { 320 | condition => 'free_only_if', 321 | table => 'AppData', 322 | name => 'NoRMName', 323 | error => 'Нет отчества', 324 | }, 325 | ], 326 | db => { 327 | table => 'AppData', 328 | name => 'RMName', 329 | }, 330 | format => 'capitalized' 331 | }, 332 | { 333 | type => 'checkbox', 334 | name => 'no_rumname', 335 | label_for => 'нет отчества', 336 | db => { 337 | table => 'AppData', 338 | name => 'NoRMName', 339 | transfer => 'nope', 340 | }, 341 | relation => {}, 342 | }, 343 | { 344 | type => 'free_line', 345 | }, 346 | { 347 | type => 'input', 348 | name => 'birthdate', 349 | label => 'Дата рождения', 350 | comment => 'Введите дату рождения', 351 | example => '31.12.1900', 352 | check => $standart_date_check, 353 | complete_check => 'not_empty', 354 | check_logic => [ 355 | { 356 | condition => 'now_or_earlier', 357 | }, 358 | ], 359 | db => { 360 | table => 'AppData', 361 | name => 'BirthDate', 362 | }, 363 | special => 'mask', 364 | }, 365 | ], 366 | 367 | 'Данные загранпаспорта' => [ 368 | { 369 | page_ord => 500, 370 | all_app_in_title => 1, 371 | progress => 5, 372 | page_db_id => 300005, 373 | }, 374 | { 375 | type => 'input', 376 | name => 'rupassnum', 377 | label => '№ загранпаспорта', 378 | comment => 'Введите серию и номер паспорта как единый набор цифр без пробелов', 379 | example => '650000001', 380 | check => 'zWN', 381 | complete_check => 'not_empty', 382 | check_logic => [ 383 | { 384 | condition => 'unique_in_pending', 385 | table => 'AppData', 386 | name => 'PassNum', 387 | }, 388 | { 389 | condition => 'rf_pass_format', 390 | full_error => 'Неверный формат загранпаспорта. Гражданам РФ необходимо ввести серию и номер паспорта как единый набор цифр без пробелов и знака N', 391 | } 392 | ], 393 | db => { 394 | table => 'AppData', 395 | name => 'PassNum', 396 | }, 397 | }, 398 | { 399 | type => 'input', 400 | name => 'lname', 401 | label => 'Фамилия', 402 | comment => 'Введите фамилию на английском языке так, как она указана в загранпаспорте', 403 | example => 'Ivanov', 404 | check => 'zW\s\-', 405 | complete_check => 'not_empty', 406 | db => { 407 | table => 'AppData', 408 | name => 'LName', 409 | }, 410 | format => 'capslock' 411 | }, 412 | { 413 | type => 'input', 414 | name => 'fname', 415 | label => 'Имя', 416 | comment => 'Введите имя на английском языке так, как оно указано в загранпаспорте', 417 | example => 'Ivan', 418 | check => 'zW\s\-', 419 | complete_check => 'not_empty', 420 | db => { 421 | table => 'AppData', 422 | name => 'FName', 423 | }, 424 | format => 'capslock' 425 | }, 426 | { 427 | type => 'free_line', 428 | }, 429 | { 430 | type => 'checkbox', 431 | name => 'ischild', 432 | label => 'Если ребёнок вписан в паспорт родителей', 433 | label_for => 'вписан в паспорт', 434 | check_logic => [ 435 | { 436 | condition => 'younger_than', 437 | offset => 18, 438 | }, 439 | ], 440 | db => { 441 | table => 'AppData', 442 | name => 'isChild', 443 | }, 444 | relation => {}, 445 | }, 446 | ], 447 | 448 | 'Вы успешно добавили заявителя' => [ 449 | { 450 | page_ord => 600, 451 | progress => 6, 452 | all_app_in_title => 1, 453 | replacer => '[app_finish]', 454 | page_db_id => 300006, 455 | }, 456 | ], 457 | 458 | 'Выберите лицо на которое будет оформлен договор' => [ 459 | { 460 | page_ord => 700, 461 | progress => 6, 462 | persons_in_page => 1, 463 | page_db_id => 300007, 464 | }, 465 | { 466 | type => 'select', 467 | name => 'visa_text', 468 | label => 'Выберите на кого оформляется', 469 | check => 'zN-', 470 | db => { 471 | table => 'Appointments', 472 | name => 'PersonForAgreements', 473 | transfer => 'nope', 474 | }, 475 | param => '[persons_in_app]', 476 | first_elements => 'default_free', 477 | }, 478 | ], 479 | 480 | 'Укажите данные документа, удостоверяющего личность' => [ 481 | { 482 | page_ord => 800, 483 | progress => 7, 484 | relation => { 485 | only_if_not => { 486 | table => 'Appointments', 487 | name => 'PersonForAgreements', 488 | value => '-1', 489 | } 490 | }, 491 | page_db_id => 300008, 492 | }, 493 | { 494 | type => 'text', 495 | name => 'rupass_text', 496 | label => 'Для граждан РФ необходимо указать данные внутреннего паспорта', 497 | }, 498 | { 499 | type => 'free_line', 500 | }, 501 | { 502 | type => 'info', 503 | name => 'info_rulname', 504 | label => 'Фамилия', 505 | db => { 506 | table => 'AppData', 507 | name => 'RLName', 508 | }, 509 | }, 510 | { 511 | type => 'info', 512 | name => 'info_rufname', 513 | label => 'Имя', 514 | db => { 515 | table => 'AppData', 516 | name => 'RFName', 517 | }, 518 | }, 519 | { 520 | type => 'info', 521 | name => 'info_rumname', 522 | label => 'Отчество', 523 | db => { 524 | table => 'AppData', 525 | name => 'RMName', 526 | }, 527 | }, 528 | { 529 | type => 'free_line', 530 | }, 531 | { 532 | type => 'input', 533 | name => 'info_passnum', 534 | label => '№ паспорта', 535 | comment => 'Введите серию и номер паспорта как единый набор цифр без пробелов', 536 | example => '4510ХХХХХХ', 537 | check => 'zNW', 538 | db => { 539 | table => 'AppData', 540 | name => 'RPassNum', 541 | }, 542 | }, 543 | { 544 | type => 'input', 545 | name => 'info_passdate', 546 | label => 'Дата выдачи', 547 | comment => 'Введите дату выдачи, указанную в паспорте', 548 | example => '31.12.1900', 549 | check => $standart_date_check, 550 | check_logic => [ 551 | { 552 | condition => 'now_or_earlier', 553 | }, 554 | ], 555 | db => { 556 | table => 'AppData', 557 | name => 'RPWhen', 558 | }, 559 | special => 'mask', 560 | }, 561 | { 562 | type => 'input', 563 | name => 'info_rupasswhere', 564 | label => 'Кем выдан', 565 | comment => 'Укажите полное название выдавшей организации, так, как она указана в паспорте', 566 | example => 'ОВД по району Беговой города Москвы', 567 | check => 'zWЁN\s\-\_\.\,\;\'\"', 568 | db => { 569 | table => 'AppData', 570 | name => 'RPWhere', 571 | }, 572 | }, 573 | { 574 | type => 'input', 575 | name => 'info_address', 576 | label => 'Адрес регистрации', 577 | comment => 'Укажите адрес регистрации', 578 | example => 'г.Москва, М.Толмачевский пер., д. 6, стр.1', 579 | check => 'zWЁN\s\-\_\.\,\;\'\"', 580 | db => { 581 | table => 'AppData', 582 | name => 'RAddress', 583 | transfer => 'nope', 584 | }, 585 | }, 586 | { 587 | type => 'input', 588 | name => 'info_phone', 589 | label => 'Телефон', 590 | comment => 'Введите контактный телефон, сотовый или городской, с кодом оператора, без пробелов и разделителей', 591 | example => '79XXXXXXXXX', 592 | check => 'zN', 593 | db => { 594 | table => 'AppData', 595 | name => 'AppPhone', 596 | }, 597 | }, 598 | ], 599 | 600 | 'Укажите данные доверенного лица' => [ 601 | { 602 | page_ord => 900, 603 | progress => 7, 604 | relation => { 605 | only_if => { 606 | table => 'Appointments', 607 | name => 'PersonForAgreements', 608 | value => '-1', 609 | } 610 | }, 611 | page_db_id => 300009, 612 | }, 613 | { 614 | type => 'input', 615 | name => 'dovlname', 616 | label => 'Фамилия', 617 | comment => 'Введите фамилию на русском языке так, как она указана во внутреннем паспорте', 618 | example => 'Иванов', 619 | check => 'zWЁ\s\-', 620 | db => { 621 | table => 'Appointments', 622 | name => 'LName', 623 | }, 624 | }, 625 | { 626 | type => 'input', 627 | name => 'dovfname', 628 | label => 'Имя', 629 | comment => 'Введите имя на русском языке так, как оно указана во внутреннем паспорте', 630 | example => 'Иван', 631 | check => 'zWЁ\s\-', 632 | db => { 633 | table => 'Appointments', 634 | name => 'FName', 635 | }, 636 | }, 637 | { 638 | type => 'input', 639 | name => 'dovmname', 640 | label => 'Отчество', 641 | comment => 'Введите отчество на русском языке так, как оно указана во внутреннем паспорте', 642 | example => 'Иванович', 643 | check => 'zWЁ\s\-', 644 | db => { 645 | table => 'Appointments', 646 | name => 'MName', 647 | }, 648 | }, 649 | { 650 | type => 'input', 651 | name => 'dovpassnum', 652 | label => '№ паспорта', 653 | comment => 'Введите серию и номер паспорта как единый набор цифр без пробелов', 654 | example => '4510ХХХХХХ', 655 | check => 'zNW', 656 | db => { 657 | table => 'Appointments', 658 | name => 'PassNum', 659 | }, 660 | }, 661 | { 662 | type => 'input', 663 | name => 'dovpassdate', 664 | label => 'Дата выдачи', 665 | comment => 'Введите дату выдачи, указанную в паспорте', 666 | example => '31.12.1900', 667 | check => $standart_date_check, 668 | check_logic => [ 669 | { 670 | condition => 'now_or_earlier', 671 | }, 672 | ], 673 | db => { 674 | table => 'Appointments', 675 | name => 'PassDate', 676 | }, 677 | special => 'mask', 678 | }, 679 | { 680 | type => 'input', 681 | name => 'dovpasswhere', 682 | label => 'Кем выдан', 683 | comment => 'Укажите полное название выдавшей организации, так, как она указана в паспорте', 684 | example => 'ОВД по району Беговой города Москвы', 685 | check => 'zWЁN\s\-\_\.\,\;\'\"', 686 | db => { 687 | table => 'Appointments', 688 | name => 'PassWhom', 689 | }, 690 | }, 691 | { 692 | type => 'input', 693 | name => 'dovaddress', 694 | label => 'Адрес', 695 | comment => 'Полный адрес, включая индекс', 696 | example => '119017, г.Москва, М.Толмачевский пер., д. 6, стр.1', 697 | check => 'zWЁN\s\-\_\.\,\;\'\"', 698 | db => { 699 | table => 'Appointments', 700 | name => 'Address', 701 | }, 702 | }, 703 | { 704 | type => 'input', 705 | name => 'dovphone', 706 | label => 'Телефон', 707 | comment => 'Введите контактный телефон, сотовый или городской, с кодом оператора, без пробелов и разделителей', 708 | example => '79161234567', 709 | check => 'zN', 710 | db => { 711 | table => 'Appointments', 712 | name => 'Phone', 713 | }, 714 | }, 715 | ], 716 | 717 | 'Оформление записи' => [ 718 | { 719 | page_ord => 1000, 720 | progress => 8, 721 | persons_in_page => 1, 722 | page_db_id => 300010, 723 | }, 724 | { 725 | type => 'text', 726 | name => 'appdate_text', 727 | label => 'Дата записи', 728 | font => 'bold', 729 | }, 730 | { 731 | type => 'free_line', 732 | }, 733 | { 734 | type => 'input', 735 | name => 'app_date', 736 | label => 'Дата записи в Визовый центр', 737 | comment => 'Введите дату, когда собираетесь посетить Визовый центр для подачи документов', 738 | check => $standart_date_check, 739 | check_logic => [ 740 | { 741 | condition => 'now_or_later', 742 | }, 743 | { 744 | condition => 'now_or_earlier', 745 | offset => 90, 746 | equality_is_also_fail => 1, 747 | full_error => 'Запись в Визовый центр более чем за [offset] не осуществляется', 748 | }, 749 | ], 750 | db => { 751 | table => 'Appointments', 752 | name => 'AppDate', 753 | }, 754 | special => 'datepicker, mask', 755 | uniq_code => 'onchange="update_timeslots(1);"', 756 | }, 757 | { 758 | type => 'select', 759 | name => 'timeslot', 760 | label => 'Время', 761 | check => 'zN', 762 | db => { 763 | table => 'Appointments', 764 | name => 'TimeslotID', 765 | }, 766 | param => '[free]', 767 | special => 'timeslots', 768 | }, 769 | { 770 | type => 'free_line', 771 | }, 772 | { 773 | type => 'free_line', 774 | }, 775 | { 776 | type => 'text', 777 | name => 'services_text', 778 | label => 'СМС-оповещение о готовности документов ( платная услуга )', 779 | font => 'bold', 780 | }, 781 | { 782 | type => 'free_line', 783 | }, 784 | { 785 | type => 'input', 786 | name => 'sms', 787 | label => 'Номер телефона для
SMS-уведомления', 788 | comment => 'Введите номер сотового телефона для получения СМС о готовности документов; услуга платная, оставьте поле пустым, если в ней нет необходимости', 789 | example => '79XXXXXXXXX', 790 | check => 'N', 791 | check_logic => [ 792 | { 793 | condition => 'length_strict', 794 | length => 11, 795 | full_error => 'Неправильный формат телефонного номера', 796 | } 797 | ], 798 | db => { 799 | table => 'Appointments', 800 | name => 'Mobile', 801 | }, 802 | }, 803 | { 804 | type => 'free_line', 805 | }, 806 | { 807 | type => 'text', 808 | name => 'services_text', 809 | label => 'Доставка документов DHL ( платная услуга )', 810 | font => 'bold', 811 | }, 812 | { 813 | type => 'free_line', 814 | }, 815 | { 816 | type => 'input', 817 | name => 'ship_index', 818 | label => 'Индекс доставки', 819 | comment => 'Введите первые цифры индекса или первые буквы города для доставки документов; выберите из списка подходящий индекс и город; услуга платная, оставьте поле пустым, если в ней нет необходимости', 820 | example => '119017, Москва', 821 | check => 'ЁN\s\,\.\-\(\)', 822 | check_logic => [ 823 | { 824 | condition => 'free_only_if_not', 825 | table => 'Appointments', 826 | name => 'ShAddress', 827 | error => 'Адрес доставки', 828 | } 829 | ], 830 | db => { 831 | table => 'Appointments', 832 | name => 'ShIndex', 833 | }, 834 | special => 'post_index', 835 | }, 836 | { 837 | type => 'input', 838 | name => 'shipping', 839 | label => 'Адрес доставки', 840 | comment => 'Введите адрес для доставки документов документов, без указания индекса и города; услуга платная, оставьте поле пустым, если в ней нет необходимости', 841 | example => 'Малый Толмачёвский пер., д.6 стр.1', 842 | check => 'ЁN\s\-\_\.\,\;\'\"', 843 | check_logic => [ 844 | { 845 | condition => 'free_only_if_not', 846 | table => 'Appointments', 847 | name => 'ShIndex', 848 | error => 'Индекс доставки', 849 | }, 850 | ], 851 | db => { 852 | table => 'Appointments', 853 | name => 'ShAddress', 854 | }, 855 | }, 856 | { 857 | type => 'free_line', 858 | }, 859 | { 860 | type => 'text', 861 | name => 'services_text', 862 | label => 'Страхование ( платная услуга )', 863 | font => 'bold', 864 | }, 865 | { 866 | type => 'free_line', 867 | }, 868 | { 869 | type => 'include', 870 | place => 'in', 871 | template => 'insurance_form.tt2', 872 | } 873 | ], 874 | 875 | 'Предпочтительный офис получения готовых документов' => [ 876 | { 877 | page_ord => 1100, 878 | progress => 9, 879 | relation => { 880 | only_if => { 881 | table => 'Appointments', 882 | name => 'CenterID', 883 | value => '1', 884 | } 885 | }, 886 | page_db_id => 300011, 887 | }, 888 | { 889 | type => 'radiolist', 890 | name => 'mezziwhom', 891 | label => 'Выберите офис, в котором будет осуществляться выдачи готовых документов', 892 | check => 'zN', 893 | db => { 894 | table => 'Appointments', 895 | name => 'OfficeToReceive', 896 | }, 897 | param => { 898 | 1 => 'м.Третьяковская, Малый Толмачёвский пер., д.6 стр.1', 899 | 2 => 'м.Киевская, ул. Киевская, вл. 2, 3 этаж', 900 | }, 901 | }, 902 | ], 903 | 904 | 'Подтвердить запись' => [ 905 | { 906 | page_ord => 1200, 907 | progress => 10, 908 | page_db_id => 300012, 909 | }, 910 | { 911 | type => 'captcha', 912 | }, 913 | ], 914 | 915 | 'Запись успешно создана!' => [ 916 | { 917 | page_ord => 1300, 918 | progress => 11, 919 | page_db_id => 300013, 920 | }, 921 | { 922 | type => 'text', 923 | name => 'conf_mail_text', 924 | label => 'На вашу почту отправлено письмо с подтверждением записи.', 925 | }, 926 | { 927 | type => 'free_line', 928 | }, 929 | { 930 | type => 'info', 931 | name => 'new_app_num', 932 | label => 'Номер записи', 933 | }, 934 | { 935 | type => 'info', 936 | name => 'new_app_branch', 937 | label => 'Визовый центр', 938 | db => { 939 | table => 'Appointments', 940 | name => 'CenterID', 941 | }, 942 | }, 943 | { 944 | type => 'info', 945 | name => 'new_app_timedate', 946 | label => 'Дата', 947 | db => { 948 | table => 'Appointments', 949 | name => 'AppDate', 950 | }, 951 | }, 952 | { 953 | type => 'info', 954 | name => 'new_app_timeslot', 955 | label => 'Время записи', 956 | db => { 957 | table => 'Appointments', 958 | name => 'TimeslotID', 959 | }, 960 | }, 961 | ], 962 | }; 963 | } 964 | 965 | 1; 966 | -------------------------------------------------------------------------------- /scripts/autoform_clean.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | 5 | use lib '/usr/local/www/data/htdocs/vcs/lib'; 6 | 7 | use VCS::Config; 8 | use VCS::Vars; 9 | use VCS::SQL; 10 | use Data::Dumper; 11 | 12 | 13 | log_file(); 14 | log_file("включение скрипта очистки autotoken"); 15 | log_file("///////////////////////////////////"); 16 | 17 | my $vars = new VCS::Vars(qw( VCS::Config VCS::SQL )); 18 | 19 | $vars->db->db_connect( $vars ); 20 | 21 | my ( $clear, $first_step, $softban_stat ) = ( 0, 0, 0 ); 22 | 23 | # /////////////// 24 | 25 | $softban_stat = $vars->db->sel1(" 26 | SELECT COUNT(ID) FROM SoftBan_stat 27 | WHERE DATEDIFF(now(), IPDate) >= 1" 28 | ); 29 | 30 | $vars->db->query(" 31 | DELETE FROM SoftBan_stat WHERE DATEDIFF(now(), IPDate) > 1" 32 | ); 33 | 34 | # /////////////// 35 | 36 | $first_step = $vars->db->sel1(" 37 | SELECT count(ID) FROM AutoToken 38 | WHERE LinkSended IS NULL AND CreatedApp IS NULL AND Finished = 0 39 | AND DATEDIFF(now(), StartDate) > 1" 40 | ); 41 | 42 | $vars->db->query(" 43 | DELETE FROM AutoToken 44 | WHERE LinkSended IS NULL AND CreatedApp IS NULL AND Finished = 0 45 | AND DATEDIFF(now(), StartDate) > 1" 46 | ); 47 | 48 | # /////////////// 49 | 50 | my $alltokens = $vars->db->selallkeys(" 51 | SELECT ID, StartDate, LastChange, EMail, LastIP, Token, AutoAppID, Finished 52 | FROM AutoToken 53 | WHERE CreatedApp IS NULL AND Finished = 0 54 | AND DATEDIFF(now(), StartDate) > 14 AND DATEDIFF(now(), LastChange) > 3" 55 | ); 56 | 57 | my $alltokens_count = scalar( @$alltokens ); 58 | 59 | # /////////////// 60 | 61 | my $completed_tokens = $vars->db->selallkeys(" 62 | SELECT AutoToken.ID, StartDate, LastChange, AutoToken.EMail, LastIP, Token, AutoAppID, Finished 63 | FROM AutoToken 64 | JOIN Appointments ON CreatedApp = Appointments.ID 65 | WHERE Finished = 1 AND AutoAppID IS NOT NULL 66 | AND DATEDIFF(now(), AppDate) > 90" 67 | ); 68 | 69 | my $completed_tokens_count = scalar( @$completed_tokens ); 70 | 71 | for my $token ( @$alltokens, @$completed_tokens ) { 72 | 73 | if ( !$token->{ Finished } ) { 74 | 75 | $vars->db->query(" 76 | INSERT INTO AutoToken_expired (Token, LastIP, EMail, StartDate, LastChange, RemovedDate) VALUES (?, ?, ?, ?, ?, now())", {}, 77 | $token->{ Token }, $token->{ LastIP }, $token->{ EMail }, $token->{ StartDate }, $token->{ LastChange } 78 | ); 79 | 80 | $vars->db->query(" 81 | DELETE FROM AutoToken WHERE ID = ?", {}, $token->{ ID } 82 | ); 83 | } 84 | 85 | $clear += 1; 86 | 87 | next if $token->{ AutoAppID } == 0 or !defined( $token->{ AutoAppID } ); 88 | 89 | $vars->db->query(" 90 | UPDATE AutoToken SET AutoAppID = NULL, AutoAppDataID = NULL, AutoSchengenAppDataID = NULL, AutoSpbDataID = NULL 91 | WHERE Token = ?", {}, $token->{ Token } 92 | 93 | ) if $token->{ Finished }; 94 | 95 | $vars->db->query(" 96 | DELETE FROM AutoAppointments WHERE ID = ?", {}, $token->{ AutoAppID } 97 | ); 98 | 99 | my $alldata = $vars->db->selallkeys(" 100 | SELECT ID, SchengenAppDataID FROM AutoAppData WHERE AppID = ?", 101 | $token->{ AutoAppID } 102 | ); 103 | 104 | for my $data ( @$alldata ) { 105 | 106 | $vars->db->query(" 107 | DELETE FROM AutoAppData WHERE ID = ?", {}, $data->{ ID } 108 | ); 109 | 110 | $vars->db->query(" 111 | DELETE FROM AutoSpbAlterAppData WHERE AppDataID = ?", {}, $data->{ ID } 112 | ); 113 | 114 | $vars->db->query(" 115 | DELETE FROM AutoSchengenAppData WHERE ID = ?", {}, $data->{ SchengenAppDataID } 116 | ); 117 | } 118 | } 119 | 120 | log_file( "всего старых записей статистики softban удалено: $softban_stat" ); 121 | log_file( "всего однодневок удалено: $first_step" ); 122 | log_file( "всего старых очищено: $clear" ); 123 | log_file( "- из них незаконченных через 14 дней: $alltokens_count" ); 124 | log_file( "- из них законченных через 90 дней: $completed_tokens_count" ); 125 | log_file( "скрипт завершился" ); 126 | 127 | 128 | 129 | sub log_file 130 | { 131 | my $msg = shift; 132 | 133 | my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = localtime( time ); 134 | 135 | $year += 1900; 136 | $mon++; 137 | 138 | for ( $sec, $min, $hour, $mday, $mon, $year) { 139 | 140 | $_ = "0$_" if $_ < 10; 141 | }; 142 | 143 | open my $file_log, '>>', '/var/log/autotoken_del.log'; 144 | 145 | print $file_log "$year-$mon-$mday $hour:$min:$sec $msg\n"; 146 | 147 | close $file_log; 148 | }; 149 | -------------------------------------------------------------------------------- /scripts/autoform_fox.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | use strict; 3 | 4 | use LWP::Simple; 5 | use XML::Simple; 6 | use Data::Dumper; 7 | use Date::Calc; 8 | use Cwd "abs_path"; 9 | 10 | use lib '/usr/local/www/data/htdocs/vcs/lib'; 11 | 12 | use VCS::Config; 13 | use VCS::Vars; 14 | use VCS::SQL; 15 | use VCS::System; 16 | use VCS::Memcache; 17 | use VCS::AdminFunc; 18 | use VCS::Site::autopayment; 19 | use VCS::Site::autodata; 20 | 21 | 22 | log_file(); 23 | log_file("Включение скрипта"); 24 | log_file("/////////////////"); 25 | 26 | my $vars = new VCS::Vars(qw( VCS::Config VCS::SQL VCS::System VCS::Memcache VCS::AdminFunc )); 27 | 28 | $vars->db->db_connect( $vars ); 29 | 30 | my $all_docs_in_fox_status = $vars->db->selallkeys(" 31 | SELECT DocPack.ID, DocPack.AgreementNo, AutoRemote.FoxIDto FROM DocPack 32 | JOIN AutoRemote ON DocPack.AppID = AutoRemote.AppID 33 | WHERE PStatus = 27 34 | "); 35 | 36 | for my $doc ( @$all_docs_in_fox_status ) { 37 | 38 | log_file( "запрос: $doc->{ AgreementNo } ( квитанция $doc->{ FoxIDto } )" ); 39 | 40 | my $status = VCS::Site::autopayment::fox_status( $vars, $doc->{ FoxIDto } ); 41 | 42 | log_file( "статус: $status" ); 43 | 44 | if ( $status eq "Груз доставлен" ) { 45 | 46 | log_file( "-----> " . close_doc( $vars, $doc->{ ID }, $doc->{ AgreementNo } ) ); 47 | 48 | log_file( "-----> " . close_app( $vars, $doc->{ ID } ) ); 49 | } 50 | } 51 | 52 | log_file( "Скрипт выключен" ); 53 | 54 | 55 | 56 | sub close_doc { 57 | 58 | my ( $vars, $doc_id, $agr ) = @_; 59 | 60 | my $doc_lists = $vars->db->selallkeys(" 61 | SELECT DocPackList.ID, PassNum, CBankID FROM DocPackList 62 | JOIN DocPackInfo ON DocPackList.PackInfoID = DocPackInfo.ID 63 | WHERE DocPackInfo.PackID = ? AND DocPackList.Status != 7", 64 | $doc_id 65 | ); 66 | 67 | $vars->db->{ dbh }->do( "UPDATE DocPack SET PStatus = 6 WHERE ID = ?", {}, $doc_id ); 68 | 69 | for ( @$doc_lists ) { 70 | 71 | $vars->db->{ dbh }->do( "UPDATE DocPackList SET Status = 6 WHERE ID = ?", {}, $_->{ ID } ); 72 | 73 | $vars->db->{ dbh }->do( " 74 | INSERT INTO DocHistory (DocID, PassNum, Login, HDate, StatusID, BankID ) 75 | VALUES ( ?, ?, ?, now(), 6, ? )", {}, 76 | $doc_id, $_->{ PassNum }, 'remote_script', $_->{ CBankID } ); 77 | } 78 | 79 | return $agr; 80 | } 81 | 82 | sub close_app { 83 | 84 | my ( $vars, $doc_id ) = @_; 85 | 86 | my $app_id = $vars->db->sel1( "SELECT AppID FROM DocPack WHERE ID = ?", $doc_id ); 87 | 88 | my $app_num = $vars->db->sel1( "SELECT AppNum FROM Appointments WHERE ID = ?", $app_id ); 89 | 90 | $vars->db->{ dbh }->do( "UPDATE AppData SET Status = 4 WHERE AppID = ? AND Status != 2", {}, $app_id ); 91 | 92 | return $app_num; 93 | } 94 | 95 | sub log_file { 96 | 97 | my $msg = shift || ''; 98 | 99 | my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = localtime( time ); 100 | $year += 1900; $mon++; 101 | 102 | for ( $sec, $min, $hour, $mday, $mon, $year ) { 103 | $_ = '0'.$_ if $_ < 10; 104 | }; 105 | 106 | open my $file_log, '>>', '/var/log/autoform_fox.log'; 107 | 108 | print $file_log "$year-$mon-$mday $hour:$min:$sec " . $msg . "\n"; 109 | 110 | close $file_log; 111 | } 112 | -------------------------------------------------------------------------------- /scripts/autoform_softban.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use LWP::Simple; 4 | use XML::Simple; 5 | use Data::Dumper; 6 | use Cwd "abs_path"; 7 | use strict; 8 | 9 | use lib '/usr/local/www/data/htdocs/vcs/lib'; 10 | 11 | use VCS::Config; 12 | use VCS::Vars; 13 | use VCS::SQL; 14 | use VCS::System; 15 | use VCS::Memcache; 16 | use VCS::AdminFunc; 17 | use Date::Calc; 18 | 19 | my $log_name = '/var/log/autoform_softban.log'; 20 | 21 | my $warn_connection = 50; 22 | 23 | my $inner_ip = { 24 | '127.0.0.1' => 1, 25 | }; 26 | 27 | log_file(); 28 | log_file("Включение скрипта подавления подозрительной активности"); 29 | log_file("//////////////////////////////////////////////////////"); 30 | 31 | my $vars = new VCS::Vars(qw( VCS::Config VCS::SQL VCS::System VCS::Memcache VCS::AdminFunc )); 32 | 33 | $vars->db->db_connect($vars); 34 | 35 | my $already_banned_array = $vars->db->selallkeys(" 36 | SELECT IP FROM SoftBan 37 | "); 38 | 39 | my %already_banned = map { $_->{ IP } => 1 } @$already_banned_array; 40 | 41 | my $connections = $vars->db->selallkeys(" 42 | SELECT LastIP AS IP, count(ID) AS ConnectionNumber, MIN(StartDate) AS Start, MAX(StartDate) AS End 43 | FROM AutoToken 44 | WHERE DATE(StartDate) = CURDATE() AND Email IS NULL 45 | GROUP BY LastIP ORDER BY ConnectionNumber DESC; 46 | "); 47 | 48 | for my $row ( @$connections ) { 49 | 50 | next if $row->{ ConnectionNumber } < $warn_connection; 51 | 52 | next if $already_banned{ $row->{ IP } }; 53 | 54 | next if exists $inner_ip->{ $row->{ IP } }; 55 | 56 | $vars->db->query(" 57 | INSERT INTO SoftBan (IP, BanDate, Reason) VALUES (?, now(), ?)", 58 | {}, $row->{ IP }, "autoform empty forms" 59 | ); 60 | 61 | log_file( $row->{ IP } . " --> " . $row->{ ConnectionNumber } ); 62 | } 63 | 64 | log_file( "Скрипт выключен" ); 65 | 66 | 67 | sub log_file { 68 | 69 | my $msg = shift || ''; 70 | 71 | my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = localtime( time ); 72 | $year += 1900; $mon++; 73 | 74 | for ( $sec, $min, $hour, $mday, $mon, $year ) { 75 | $_ = '0'.$_ if $_ < 10; 76 | }; 77 | 78 | open my $file_log, '>>', $log_name; 79 | 80 | print $file_log "$year-$mon-$mday $hour:$min:$sec " . $msg . "\n"; 81 | 82 | close $file_log; 83 | } 84 | -------------------------------------------------------------------------------- /scripts/autoform_softban_warn.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use LWP::Simple; 4 | use XML::Simple; 5 | use Data::Dumper; 6 | use Cwd "abs_path"; 7 | use strict; 8 | 9 | use lib '/usr/local/www/data/htdocs/vcs/lib'; 10 | 11 | use VCS::Config; 12 | use VCS::Vars; 13 | use VCS::SQL; 14 | use VCS::System; 15 | use VCS::Memcache; 16 | use VCS::AdminFunc; 17 | use Date::Calc; 18 | 19 | my $log_name = '/var/log/autoform_softban_warn.log'; 20 | 21 | my @addresses = ( 22 | 'mail@mail.com', 23 | ); 24 | 25 | my $signature = 26 | 'С уважением,
Скрипт отчёта о подозрительной активности'; 27 | 28 | log_file(); 29 | log_file("Включение скрипта проверки заблокированной активности"); 30 | log_file("/////////////////////////////////////////////////////"); 31 | 32 | my $vars = new VCS::Vars(qw( VCS::Config VCS::SQL VCS::System VCS::Memcache VCS::AdminFunc )); 33 | 34 | $vars->db->db_connect($vars); 35 | 36 | my $connections = $vars->db->selallkeys(" 37 | SELECT IP, BanDate, Reason FROM SoftBan 38 | WHERE DATE(BanDate) = (CURDATE() - INTERVAL 1 DAY) ORDER BY BanDate 39 | "); 40 | 41 | my $table = create_table( $connections ); 42 | 43 | unless ( defined $table ) { 44 | 45 | log_file( "Ничего подозрительного НЕ было" ); 46 | } 47 | else { 48 | my $subject = 'Отчёт о подавлении подозрительной внешней активности'; 49 | my $body = $table . "
Данные за прошедшие сутки
Все указанные адреса заблокированы

" . $signature; 50 | 51 | for ( @addresses ) { 52 | $vars->get_system->send_mail( $vars, $_, $subject, $body ); 53 | log_file( "Отправлено сообщение на $_" ); 54 | } 55 | } 56 | 57 | log_file( "Скрипт выключен" ); 58 | 59 | 60 | 61 | sub log_file { 62 | my $msg = shift || ''; 63 | my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = localtime( time ); 64 | $year += 1900; $mon++; 65 | for ( $sec, $min, $hour, $mday, $mon, $year ) { 66 | $_ = '0'.$_ if $_ < 10; 67 | }; 68 | 69 | open my $file_log, '>>', $log_name; 70 | print $file_log "$year-$mon-$mday $hour:$min:$sec " . $msg . "\n"; 71 | close $file_log; 72 | } 73 | 74 | sub create_table { 75 | 76 | my $connections = shift; 77 | 78 | my $table = ''; 79 | 80 | my $tdheadstyle = 'style="border:1px solid black;padding:5px;background-color: lightgray;"'; 81 | my $tdstyle = 'style="border:1px solid black;padding:5px;"'; 82 | 83 | my $n = 0; 84 | 85 | $_->{ N } = ++$n for @$connections; 86 | 87 | my @heads = ( 'N', 'IP', 'BanDate', 'Reason' ); 88 | 89 | $table .= "" for ( @heads ); 90 | 91 | $table .= ""; 92 | 93 | my $line = 0; 94 | 95 | for my $row ( @$connections ) { 96 | 97 | $line += 1; 98 | 99 | log_file( $row->{ IP } ); 100 | 101 | $table .= ""; 102 | 103 | for my $column ( @heads ) { 104 | 105 | $table .= ""; 106 | } 107 | 108 | $table .= ""; 109 | } 110 | 111 | $table .= "
$_
" . $row->{ $column } . "
"; 112 | 113 | return undef if $line == 0; 114 | 115 | return $table; 116 | } 117 | -------------------------------------------------------------------------------- /templates/autoform.tt2: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | VMS - [% langreq('Новая запись') %] 14 | 15 | [% IF special.multiple_select %] 16 | 17 | 18 | [% END %] 19 | 20 | [% IF ( special.datepicker.0 || special.post_index.0 || special.mask.0 ) %] 21 | 22 | 23 | 24 | [% END %] 25 | 26 | [% IF ( special.mask.0 || (step == 2) ) %] 27 | 28 | [% END %] 29 | 30 | [% IF ( special.sms_code) %] 31 | 32 | 33 | [% END %] 34 | 35 | [% IF javascript_check %] 36 | 39 | [% ELSE %] 40 | 43 | [% END %] 44 | 45 | 46 | 47 |
48 |
49 | 50 | 67 | 68 |
69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 160 |
[% progress %]



81 | 82 | 83 | 84 | 85 | [% content_text %] 86 | 87 | [% FOREACH include_name IN special.include_in %] 88 | [% INCLUDE $include_name %] 89 | [% END %] 90 | 91 | 131 | [% END %] 132 | 133 | 149 | 150 | [% IF step == 1 %] 151 | 152 | [% END %] 153 | 154 | [% FOREACH include_name IN special.include_out %] 155 | [% INCLUDE $include_name %] 156 | [% END %] 157 |

[% langreq(title) %]



92 | 93 | [% IF ( step > min_step ) && ( step != max_step ) %] 94 | 95 |   96 | [% END %] 97 | 98 | 99 | [% IF ( special.payment.0) %] 100 | 101 |   102 | [% ELSIF ( step < max_step ) && ( step > 0 ) %] 103 | 104 |   105 | [% END %] 106 | 107 | 108 | [% IF ( step == max_step ) %] 109 | 110 | [% IF (service_type == 2) %] 111 | 112 | [% ELSIF mobile_app %] 113 | 114 | [% ELSE %] 115 | 116 | [% END %] 117 | [% END %] 118 | 119 | [% IF step == 1 %] 120 |

121 | [% langreq('Отказ от ответственности и политика конфиденциальности') %] 130 |

134 | [% IF error_page != 'error' %] 135 | [% IF lang_in_link != 'ru' %] 136 | Перейти на русский язык  137 | [% END %] 138 | 139 | [% IF lang_in_link != 'en' %] 140 | Switch to English  141 | [% END %] 142 | 143 | [% IF lang_in_link != 'it' %] 144 | Passare all′italiano 145 | [% END %] 146 |   147 | [% END %] 148 |
 
158 | 159 |
161 | 162 |
163 | 164 | 167 | 168 |
169 |
170 | 171 | 172 | -------------------------------------------------------------------------------- /templates/autoform_address_check.tt2: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | VMS - [% langreq('Новая запись') %] 12 | 13 | 14 | 15 | 16 |
17 |
18 | 19 | 32 | 33 |
34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
[% progress %]



44 | 45 | 46 | 47 | 48 | 104 | 105 | 106 | 116 | 129 |

[% langreq(title) %]


49 | 50 |
51 | [% langreq('Если Вы планируете воспользоваться услугой Дистанционной подачи документов — Вы можете проверить обслуживается ли ваш адрес курьерской службой и узнать ориентировочную стоимость пересылки.') %] 52 |

53 | 54 | [% langreq('Онлайн-проверка документов является неотъемлемой частью услуги по Дистанционной подаче.
После успешной проверки, при желании, Вы сможете оформить и оплатить заявку на данную услугу и передать Ваши документы сотруднику курьерской службы для их последующего предоставления в Консульство. ') %] 55 |

56 | [% langreq('Обращаем Ваше внимание, что Генеральным Консульством установлен минимальный срок рассмотрения визового заявления — от 8 рабочих дней. Данный период рассмотрения не включает в себя сроки предварительной проверки документов онлайн, оформления Вами заявки на услугу Дистанционной подачи, доставки Комплекта документов в Визовый центр и Готовых паспортов обратно Заявителю.') %] 57 |
58 |

59 | [% langreq('Начните ввод своего адреса и выберите подходящий адрес из предложенных вариантов.') %] 60 |

61 | 62 | [% langreq('Обратите внимание, что нужен полный адрес, обязательно включающий адрес квартиры.') %]
63 |

64 | 65 |
66 | [% langreq('пример: Москва Толмачёвский М. д 6 кв 1') %] 67 |
68 | 72 | 88 | 89 | 93 | 94 | 97 | 98 | 102 | 103 |
 
107 | 108 | 109 | 110 |   111 | 112 | 113 | 114 | 115 |

117 | [% IF lang_in_link != 'ru' %] 118 | Перейти на русский язык  119 | [% END %] 120 | 121 | [% IF lang_in_link != 'en' %] 122 | Switch to English  123 | [% END %] 124 | 125 | [% IF lang_in_link != 'it' %] 126 | Passare all′italiano 127 | [% END %] 128 |
130 | 131 |
132 | 133 |
134 | 135 | 342 | 343 | [% INCLUDE yandex_metrika.tt2 %] 344 | 345 |
346 | -------------------------------------------------------------------------------- /templates/autoform_confirm.tt2: -------------------------------------------------------------------------------- 1 | 2 |
3 | E-mail Template 4 | 7 | 9 | 12 | 14 | 15 | 61 | 104 | 105 | 106 | 110 | 111 | 112 |
17 |
19 |
[%app_tx%]
21 |
22 |
24 |
27 |

[%date_time%]

29 |
30 |
33 |

[%app_num%]

35 |
36 |
39 |

[%app_person%]

41 |
42 |
[%list_tx%]
45 |

[%app_list%]

47 |
48 |
49 |
50 |
51 |
[%vms_tx%]
52 |
53 |
54 |
55 | [%dis_head%]
56 | [%dis_tx%]
57 |
58 |
[%no_reply_head%]

59 | [%no_reply%]
60 |
63 |
67 |
[%branch_tx%]
68 |
70 |
[%branch_addr%]
71 | Email: [%app_email%]
73 | Website: [%app_website%] 76 |
77 |
78 | [%info_btn%] [%resh_btn%] 90 | [%canc_btn%] 96 | [%prnt_btn%] 102 | [%edit_app_button%] 103 |
108 | 109 |
113 |
114 | -------------------------------------------------------------------------------- /templates/autoform_docstatus.tt2: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | VMS - [% langreq('Статус документов') %] 12 | 13 | 14 | 15 | 24 | 25 | 26 | 27 |
28 | 29 |
30 | 31 | 32 |

33 |
34 | 35 | 36 |
37 |
[% langreq('Статус рассмотрения Ваших документов') %]: 38 |


39 | 40 | 41 | [% content_text %] 42 |



43 | 44 |
45 | 46 | -------------------------------------------------------------------------------- /templates/autoform_edit.tt2: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | VMS - [% langreq('Информация о записи') %] 10 | 11 | [% IF ( special.datepicker.0 || special.post_index.0 || special.mask.0 ) %] 12 | 13 | 14 | 15 | [% END %] 16 | 17 | [% IF ( special.mask.0 || (step == 1) ) %] 18 | 19 | [% END %] 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
33 |
34 | 35 | 50 | 51 |
52 | 53 | 54 | 55 | 56 | 57 |
58 | 59 | 60 | 61 | 64 | 65 | [% content_text %] 66 | 67 | 71 | 72 | 82 | 83 | 96 | 97 | 98 | 99 |
62 |

63 |

[% langreq('Внести правки в данные заявителя') %]



68 |
[% langreq('Вы можете отредактировать все поля') %].
69 |
  [% langreq('Пожалуйста, будьте внимательны при редактировании всех полей записи') %]
70 |

73 | 74 | 75 |   76 | 77 | 78 | 79 |   80 | 81 |

84 | [% IF lang_in_link != 'ru' %] 85 | Перейти на русский язык  86 | [% END %] 87 | 88 | [% IF lang_in_link != 'en' %] 89 | Switch to English  90 | [% END %] 91 | 92 | [% IF lang_in_link != 'it' %] 93 | Passare all′italiano 94 | [% END %] 95 |
 
100 | 101 | 102 | 103 | [% INCLUDE metrika.tt2 %] 104 | 105 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /templates/autoform_finish.tt2: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | VMS - [% langreq('Новая запись') %] 8 | 9 | 10 | 11 | 12 |
13 |
14 | 15 | 29 | 30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | 40 | 41 |
38 | [% progress %]



39 |
42 | 43 | 44 | 45 | 46 | 49 | 50 | 52 | 53 | 65 | 66 |

[% langreq(title) %]


47 | [% langreq('Вернуться к списку, добавить ещё одного заявителя или перейти к завершению записи?') %] 48 |
  51 |
54 | 55 | 56 |

57 | 58 | 59 | 60 |   61 | 62 | 63 | 64 |
 
67 | 68 | 69 | 70 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /templates/autoform_info_entry.tt2: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | VMS - [% langreq('Информация о записи') %] 9 | 10 | 11 | 12 | 13 |
14 |
15 | 16 | 29 | 30 |
31 | 32 | 33 | 34 | 35 |
36 | 37 | 38 | 39 | 42 | 43 | 46 | 47 | 50 | 51 | 52 | 53 | 54 | 55 | 57 | 58 | 59 | 62 | 63 | 66 | 67 |
40 | 41 |




44 | 45 |

[% langreq('Информация о записи') %]

48 |
[% langreq('Вы также можете войти по ссылке из письма, которое получили после начала записи') %].

49 |
пример: 001/2018/01/01/0001

56 |
пример: 650000001
60 |
61 |

64 | 65 |
68 | 69 | 70 | 71 | 109 | 110 | [% INCLUDE metrika.tt2 %] 111 | 112 | 113 | -------------------------------------------------------------------------------- /templates/autoform_list.tt2: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | VMS - [% langreq('Новая запись') %] 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 | 30 | 31 |
32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
[% progress %]



42 | 43 | 44 | 45 | 46 | [% IF content_text.0.ID == "X" %] 47 | [% IF service_type == 2 %] 48 | 58 | [% ELSE %] 59 | 64 | [% END %] 65 | [% ELSE %] 66 | [% SET i = 0 %][% FOREACH person IN content_text %][% SET i = i + 1 %] 67 | 68 | 69 | 79 | 80 | 82 | 84 | 85 | [% END %] 86 | 89 | [% END %] 90 | 91 | [% IF (content_text.0.ID == "X") && (service_type != 2) %] 92 | 99 | [% END %] 100 | 101 | 115 | 128 |

[% langreq(title) %]


49 | [% langreq('Вы ещё не зарегистрировали ни одного заявителя в данной записи') %].
50 | [% langreq('Сделайте это прямо сейчас, нажав на кнопку "Следующий заявитель"') %]!

51 | 52 | [% langreq('После заполнения данных первого заявителя, Вы сможете добавить данные остальных заявителей') %].

53 | [% langreq('Обратите внимание, что необходимо внести данные всех заявителей, которым необходима проверка документов. На каждого из них будет автоматически сформирована анкета') %].

54 | [% langreq('На указанную Вами электронную почту будет отправлено письмо с результатами онлайн проверки документов') %].

55 | [% langreq('Если вы не получили его в течение часа, проверьте папку нежелательные сообщения (спам)') %]. 56 |


57 |
60 | [% langreq('Вы ещё не зарегистрировали ни одного заявителя в данной записи') %].
61 | [% langreq('Сделайте это прямо сейчас, нажав на кнопку "Следующий заявитель"') %]!

62 | [% langreq('После заполнения данных первого заявителя, Вы сможете добавить последующих. Обратите внимание, что необходимо внести всех заявителей, которым необходима виза') %].
63 |
[% i %]. 70 | [% IF person.Finished == 4 %][[% langreq('черновик') %]] 71 | [% ELSIF person.Finished == 19 %][[% langreq('тип визы') %]] 72 | [% ELSIF person.Finished == 22 %][[% langreq('в.центр') %]] 73 | [% END %] 74 | [% IF (person.FName != '') || (person.LName != '') %] 75 | [% person.FName %] [% person.LName %] 76 | [% ELSE %] 77 | ([% langreq('ФИО пока не указано') %]) 78 | [% END %][% IF person.BirthDate != '00.00.0000' %][% person.BirthDate %][% ELSE %] [% END %] 81 | 83 |
87 |
 
88 |

93 | [% langreq('На указанную Вами электронную почту отправлено письмо со ссылкой, перейдя по которой, Вы сможете:') %]

94 | 95 | [% langreq('1. Продолжить запись в Визовый центр, которую Вы начали не более 14 дней назад.

2. После завершения записи Вы сможете получать информацию о своей записи, отменить её или перенесети на другое время, распечатать уже заполненную шенгенскую анкету.

3. После подачи Вы сможете отслеживать статус документов, их отправку в Консульство и готовность к получению.') %]
96 | 97 |

[% langreq('Если вы не получили письмо в течение часа, проверьте папку нежелательные сообщения (спам)') %].

98 |
102 | 103 | 104 | 105 |   106 | 107 | [% IF i < max_applicants %] 108 | 109 | [% ELSE %] 110 | 111 | [% END %] 112 | 113 | 114 |

116 | [% IF lang_in_link != 'ru' %] 117 | Перейти на русский язык  118 | [% END %] 119 | 120 | [% IF lang_in_link != 'en' %] 121 | Switch to English  122 | [% END %] 123 | 124 | [% IF lang_in_link != 'it' %] 125 | Passare all′italiano 126 | [% END %] 127 |
129 | 130 |
131 | 132 |
133 | 134 | 219 | 220 | [% INCLUDE metrika.tt2 %] 221 | 222 |
223 | -------------------------------------------------------------------------------- /templates/autoform_pcode.tt2: -------------------------------------------------------------------------------- 1 | [% callback %]({"cmps":[[% SET i = 0 %][% FOREACH aid IN alist %][% IF i > 0 %],[% END %]{"cid":"[% aid.ID %]","cname":"[% aid.CName %]","pcode":"[% aid.PCode %]","cdefault":"[% aid.isDefault %]"}[% SET i = i + 1%][% END %]],"totalResultsCount":[% i %]}) -------------------------------------------------------------------------------- /templates/autoform_upload.tt2: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | VMS - [% langreq('Новая запись') %] 11 | 12 | 13 | 14 | 15 |
16 |
17 | 18 | 35 | 36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 |
[% progress %]



47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 59 | 60 | 61 | 62 | 164 | 165 | 166 | 167 | 177 | 190 |

[% langreq(title) %]


[% langreq('Тип визы') %]: [% content_text.visatype%]
 
56 | 57 | [% langreq('Всю необходимую информацию о наборе документов вы можете узнать на ') %] [% langreq('соответствующей странице') %] [% langreq('нашего сайта') %]. [% langreq('Документы на проверку предоставляются в виде отсканированных копий и (или) фотографий. Допустимы к загрузке изображения в форматах JPEG, BMP, PNG, TIFF, а также файлы PDF. Обратите внимание на то, что все загружаемые изображения должны быть хорошего качества. Максимально допустимый размер загружаемого файла') %] [% content_text.max_size_mb %] [% langreq('МБ') %].

58 | [% langreq('Пожалуйста, обратите внимание, что Консульством установлен минимальный срок рассмотрения визового заявления - от 8 рабочих дней. Данный период рассмотрения не включает в себя сроки предварительной проверки документов онлайн, оформления Вами заявки на услугу Дистанционной подачи, доставки Комплекта документов в Визовый центр и Готовых паспортов обратно Заявителю') %].
 
63 | [% FOREACH doc IN content_text.doc_list %] 64 | 65 | 70 | 78 | 79 | 82 | 83 | [% IF ( ( doc.uploaded != 1 ) || ( doc.multiple > 0 ) ) %] 84 | 85 | [% ELSE %] 86 | 92 | 95 | 96 | 109 | [% END %] 110 | 111 | 119 | 120 | [% IF ( doc.multiple > 0 ) %] 121 | [% FOREACH file IN doc.files %] 122 | 123 | 124 | 126 | 127 | 132 | 135 | 136 | 142 | 143 | 146 | 147 | [% END %] 148 | [% END %] 149 | 150 | [% END %] 151 | 152 | 153 | 157 | 161 | 162 | 163 |
66 | [% IF ( doc.uploaded > 0 ) %] 67 | 68 | [% END %] 69 |   71 | [% langreq(doc.title) %] 72 | [% IF (doc.help != '') %] 73 | [?] 74 | [% ELSIF (doc.comment != '') %] 75 | [?] 76 | [% END %] 77 |   87 | 88 | [% IF doc.files.0.type != '' %] 89 | 90 | [% END %] 91 | 93 | [% doc.files.0.name %] 94 | 112 | [% IF ( ( ( doc.uploaded < 1 ) || ( doc.multiple > 0 ) ) && !( doc.id < 0 ) ) %] 113 | 114 | 0 ) && (doc.total_uploaded >= doc.multiple ) ) %]disabled[% END %] onclick="document.getElementById('upfile_[% doc.id %]').click();" /> 115 | [% ELSE %] 116 | 117 | [% END %] 118 |
  125 | [% langreq(doc.title) %]   128 | [% IF file.type != '' %] 129 | 130 | [% END %] 131 | 133 | [% file.name %] 134 | 144 | 145 |

154 | [% langreq('Загрузить дополнительный документ по вашему усмотрению') %] 155 | 156 | 158 | 159 | 160 |
 
168 | 169 | 170 |   171 | 172 | 173 | 174 |   175 | 176 |

178 | [% IF lang_in_link != 'ru' %] 179 | Перейти на русский язык  180 | [% END %] 181 | 182 | [% IF lang_in_link != 'en' %] 183 | Switch to English  184 | [% END %] 185 | 186 | [% IF lang_in_link != 'it' %] 187 | Passare all′italiano 188 | [% END %] 189 |
191 | 192 |
193 | 194 |
195 | 196 | 491 | 492 |
493 | -------------------------------------------------------------------------------- /templates/js_elements.tt2: -------------------------------------------------------------------------------- 1 | $(document).ready(mobileScreenCheck); 2 | 3 | var ua = window.navigator.userAgent.toLowerCase(); 4 | if ( (/trident/gi).test(ua) || (/msie/gi).test(ua) ) { 5 | 6 | function ie_select_bugfix(field, size) { 7 | 8 | $(field).attr("size", size); 9 | return "select[tabindex='" + (parseInt($(field).attr('tabindex'), 10) + 1) + "']"; 10 | } 11 | 12 | $(document).ready(function(){ 13 | $('select').focus(function(){ 14 | $(ie_select_bugfix(this, 6)).fadeTo(50, 0); 15 | }); 16 | $('select').blur(function(){ 17 | $(ie_select_bugfix(this, 1)).fadeTo('fast', 1.0); 18 | }); 19 | }); 20 | } 21 | 22 | function mobileScreenCheck() { 23 | 24 | [% FOREACH post_index IN special.post_index %] 25 | $('#[% post_index %]').autocomplete("widget").css("width", ( mobilScreen ? 600 : 300 )); 26 | $('#[% post_index %]').autocomplete("widget").css({"font-size": ( mobilScreen ? '30px' : '14px' )}); 27 | [% END %] 28 | 29 | if ( !mobilScreen ) { 30 | 31 | init_comm(); 32 | 33 | $('#progressbar').css( "display", 'table' ); 34 | $('#app_form').css( "margin", '50px' ); 35 | $('#ui-datepicker-div').css( "font-size", "12" ); 36 | $('#app_table').attr( "width", '590px' ); 37 | $('.input_width').css( "width", '20em' ); 38 | 39 | $('#separator').html('  '); 40 | 41 | [% IF (last_error_name && (last_error_name != 'timeslot')) %] 42 | show_error_tip( '[% last_error_name %]', '[% langreq(last_error_text) %]' ); 43 | [% END %] 44 | 45 | return; 46 | } 47 | 48 | $('#mobile_ver').val(1); 49 | 50 | $('#progressbar').css( "display", 'none' ); 51 | $('#app_form').css( "margin", '0px' ); 52 | 53 | $('.action_button').css( "height", '60px' ); 54 | $('.action_button').css( "width", '100%' ); 55 | 56 | $('#app_table').attr( "cellspacing", '10' ); 57 | $('#app_table').attr( "width", '100%' ); 58 | 59 | var temp_span_content = $('#mobile_order_bottom').html(); 60 | $('#mobile_order_bottom').html($('#mobile_order_top').html()); 61 | $('#mobile_order_top').html(temp_span_content); 62 | 63 | $("#app_table").each(function(){ 64 | $("td",this).each(function(){ 65 | if (!$(this).hasClass("no_mobile_transform")) { 66 | $(this).css( "display", 'block' ); 67 | $(this).css( "float", 'left' ); 68 | $(this).css( "width", '100%' ); 69 | } 70 | }); 71 | }); 72 | 73 | $('*').css( "font-size", '15px' ); 74 | 75 | $('.input_width').css( "line-height", '40px' ); 76 | $('.input_width').css( "height", '40px' ); 77 | $('.input_width').css( "max-width", '95%' ); 78 | $('.input_width, .info').css( "font-size", '30px' ); 79 | $('.input_width').css( "width", ( isIphone() ? '90%' : '100%' ) ); 80 | 81 | $('h2').css( "font-size", '20px' ); 82 | $('h2, .bold_text').css( "color", '#FF6666' ); 83 | 84 | $(':checkbox, :radio').css( "height", "20px" ); 85 | $(':checkbox, :radio').css( "width", "20px" ); 86 | 87 | $('#separator').html('

'); 88 | 89 | $('.mobil_hide').css( "display", 'none' ); 90 | 91 | $('#app_form').show(); 92 | 93 | [% IF (last_error_name && (last_error_name != 'timeslot')) %] 94 | show_error_tip( '[% last_error_name %]', '[% langreq(last_error_text) %]' ); 95 | [% END %] 96 | } 97 | 98 | function go_to_new_appointment() { 99 | window.location.replace("/autoform/"); 100 | } 101 | 102 | function go_button(where) { 103 | 104 | [% IF ( step == max_step ) %] 105 | 106 | if (where == 'app') { 107 | location.replace('[% addr %]?t=[% token %][% IF lang_in_link %]&lang=[% lang_in_link %][% END %]'); 108 | return; 109 | } 110 | [% END %] 111 | 112 | [% IF mobile_app %] 113 | 114 | if (where == 'mobile_app') { 115 | 116 | location.replace('[% addr %]mobile_end.htm'); 117 | return; 118 | } 119 | [% END %] 120 | 121 | if ((where == 'forward') || (where == 'save_edit_app')) { 122 | 123 | [% IF ( ( step + 1 ) == max_step ) %] 124 | $('#next_button').prop('disabled', true); 125 | [% END %] 126 | 127 | if ( check_all_inputs_errors() > 0 ) { 128 | return; 129 | } 130 | } 131 | 132 | $('#action').val(where); 133 | 134 | document.dataform.submit(); 135 | }; 136 | 137 | function init_poshytip(cls, fcs, aTo, aX, aY, ofX, ofY) { 138 | 139 | $(cls).poshytip({ 140 | className: 'tip-yellowsimple', 141 | showOn: fcs, 142 | alignTo: aTo, 143 | alignX: aX, 144 | alignY: aY, 145 | offsetX: ofX, 146 | offsetY: ofY, 147 | showTimeout: 100 148 | }); 149 | } 150 | 151 | function init_comm() { 152 | 153 | $('.input_gen, .select_gen,').poshytip('destroy'); 154 | 155 | if ( document.body.clientWidth < 1000 ) { 156 | init_poshytip('.input_gen', 'focus', 'target', 'center', 'top', 5, 6); 157 | } else { 158 | init_poshytip('.input_gen', 'focus', 'target', 'right', 'center', 5, 0); 159 | } 160 | 161 | init_poshytip('.select_gen', 'focus', 'target', 'center', 'top', 5, 6); 162 | init_poshytip('label', '', 'target', 'right', 'center', 5, 0); 163 | init_poshytip(':radio, :checkbox', '', 'target', 'right', 'center', 200, 0); 164 | 165 | $('.tip-yellowsimple, .tip-inner ').css( "font-size", ( mobilScreen ? '35px' : '' ) ); 166 | $('.tip-yellowsimple, .tip-inner ').css( "line-height", ( mobilScreen ? '1.2' : '' ) ); 167 | } 168 | 169 | [% FOREACH picker IN special.datepicker %] 170 | 171 | create_datepicker("[% picker %]"); 172 | 173 | [% END %] 174 | 175 | [% FOREACH mask IN special.mask %] 176 | 177 | $("#[% mask %]").mask("99.99.9999", { placeholder: "__.__.____" }); 178 | 179 | if ( mobilScreen ) { 180 | create_datepicker("[% mask %]"); 181 | } 182 | [% END %] 183 | 184 | [% FOREACH mask IN special.full_mask %] 185 | 186 | $("#[% mask.0 %]").mask("[% mask.1 %]"); 187 | [% END %] 188 | 189 | [% FOREACH phone IN special.phone_correct %] 190 | 191 | $("#[% phone %]").bind("paste", function(e){ 192 | e.preventDefault(); 193 | var text = (e.originalEvent || e).clipboardData.getData('text/plain').replace(/\D/g, ''); 194 | if ((text.length > 10) && ((text.charAt(0) == '8') || (text.charAt(0) == '7'))) { 195 | text = text.substr(1); 196 | } 197 | $("#[% phone %]").val(text); 198 | } 199 | ); 200 | [% END %] 201 | 202 | [% IF ( special.payment.0) %] 203 | 204 | function pay() { 205 | 206 | window.open('[% payment.form_url %]'); 207 | } 208 | 209 | [% END %] 210 | 211 | 212 | [% IF ( special.datepicker.0 || special.mask.0 ) %] 213 | 214 | function create_datepicker(date_id) { 215 | 216 | $('#'+date_id).datepicker({ 217 | dateFormat: 'dd.mm.yy', 218 | firstDay: 1, 219 | showOn: 'both', 220 | buttonImage: '[% static %]/images/1x1.png', 221 | buttonImageOnly:true, 222 | 223 | [% FOREACH relation IN special.min_date %] 224 | [% IF (relation.min != 'current') %] 225 | 226 | onSelect: function(date){ 227 | if ( date_id == '[% relation.min %]') { 228 | 229 | var minDate = get_date_from(date_id); 230 | $('#[% relation.name %]').datepicker("option", "minDate", minDate); 231 | } 232 | } 233 | [% END %] 234 | [% END %] 235 | }); 236 | 237 | $('#'+date_id).datepicker( "option", "disabled", true ); 238 | }; 239 | [% END %] 240 | 241 | [% FOREACH minimal_date IN special.min_date %] 242 | 243 | [% IF (minimal_date.min == 'current') %] 244 | var minDate = new Date(); 245 | [% ELSE %] 246 | var minDate = get_date_from('[% minimal_date.min %]'); 247 | [% END %] 248 | 249 | $('#[% minimal_date.name %]').datepicker("option", "minDate", minDate); 250 | 251 | [% END %] 252 | 253 | [% IF (special.min_date.0) %] 254 | 255 | function get_date_from(date_id) { 256 | 257 | var minDateLine = $('#'+date_id).datepicker('getDate'); 258 | var minDate = new Date( Date.parse( minDateLine ) ); 259 | 260 | return minDate; 261 | } 262 | [% END %] 263 | 264 | [% FOREACH select IN special.multiple_select %] 265 | $('#[% select %]').multipleSelect({width: '100%'}); 266 | [% END %] 267 | 268 | 269 | [% FOREACH no_copy IN special.no_copypast %] 270 | 271 | $('#[% no_copy %]').live("keydown", function(e){ 272 | 273 | var e = e || event, k = e.which || e.button; 274 | 275 | if ( e.ctrlKey && k == 86 ) return false; 276 | }); 277 | 278 | $('#[% no_copy %]').bind("contextmenu", function(e) { 279 | 280 | e.preventDefault(); 281 | }); 282 | 283 | [% END %] 284 | 285 | [% FOREACH near IN special.nearest_date %] 286 | 287 | update_nearest_date_[% near %](); 288 | 289 | var whatisnearestdate = ' [% langreq('( что это за дата? )') %]'; 290 | 291 | function update_nearest_date_[% near %](without_vtype) 292 | { 293 | 294 | 295 | if ($('#center').val() != 0) { 296 | $("#[% near %]").html("
"); 297 | 298 | $.get("[% vcs_tools %]get_nearest.htm", { 299 | 'center': $('#center').val(), 300 | 'persons': $('#num_of_person').val(), 301 | 'urgent':0 }, 302 | function(data) { 303 | $("#[% near %]").html(data + (/^\d{2}\.\d{2}\.\d{4}$/.test(data) ? whatisnearestdate : '')); 304 | } 305 | ); 306 | } 307 | 308 | if ( !without_vtype ) { 309 | 310 | var selected_el = $('#vtype').val(); 311 | var restore_el = 0; 312 | 313 | $('#vtype').hide(); 314 | 315 | if ( ! ( $('#tmp_vtype_img').length > 0 ) ) { 316 | $('#vtype').parent().prepend("
"); 317 | } 318 | 319 | if ( mobilScreen ) { 320 | $("#tmp_vtype_img, #tmp_near_img").css('height', '38px'); 321 | } 322 | 323 | $('#vtype').find('option').remove(); 324 | 325 | $.get("[% vcs_tools %]get_vtypes.htm", 326 | { 327 | 'center': $('#center').val() 328 | [% IF ( service_type == 10 ) OR ( service_vtype == 19 ) %], 'rinnuovo': 1[% END %] 329 | }, 330 | function(xml) { 331 | $(xml).find('node').each( function() { 332 | $('#vtype').append( 333 | '' 336 | ); 337 | 338 | if ($(this).find('id').text() == selected_el) { restore_el = 1; }; 339 | }); 340 | 341 | if (restore_el) { 342 | $('#vtype').val(selected_el); 343 | } 344 | $('#tmp_vtype_img').remove(); 345 | $('#vtype').show(); 346 | 347 | }, 348 | 'xml'); 349 | } 350 | } 351 | [% END %] 352 | 353 | [% FOREACH timeslot IN special.timeslots %] 354 | 355 | update_timeslots(); 356 | 357 | function update_timeslots(date_change) { 358 | 359 | $('#timeslot').hide(); 360 | 361 | $('#timeslot').find('option').remove(); 362 | 363 | $('#timeslot').parent().prepend(""); 364 | 365 | var reload_timeslot = $('#timeslot').attr('data-timeslot'); 366 | 367 | 368 | $.get("[% vcs_tools %]get_times.htm", { 369 | 370 | 'vtype': '[% appinfo.vtype %]', 371 | 'center': '[% appinfo.center %]', 372 | 'persons': '[% appinfo.persons %]', 373 | 'appdate':$('#app_date').val(), 374 | 'urgent_allowed':'[% urgent_allowed %]', 375 | 'fdate': '[% appinfo.fdate %]', 376 | 'lang': '[% lang_in_link %]', 377 | 378 | }, function(xml) { 379 | $(xml).find('node').each( function() { 380 | 381 | var apptimeValue = $(this).find('id').text(); 382 | var apptimeText = $(this).find('title').text().split("—")[0]; 383 | var defaultOpt = $(this).find('default').text(); 384 | 385 | $('#timeslot').append( 386 | '' 395 | ); 396 | }); 397 | 398 | $('#tmp_img').remove(); 399 | $('#timeslot').show(); 400 | 401 | [% IF last_error_name == 'timeslot' %] 402 | 403 | if ( !date_change ) { 404 | 405 | $(document).ready(function() { 406 | show_error_tip( 'timeslot', '[% langreq(last_error_text) %]' ); 407 | }); 408 | } else { 409 | $('#timeslot').poshytip('destroy'); 410 | } 411 | [% END %] 412 | 413 | var al = $(xml).find('urgent_flag'); 414 | 415 | if (al.text() != '') { 416 | 417 | alert(al.text()); 418 | 419 | $('#urgent_slots').val(1); 420 | } else { 421 | $('#urgent_slots').val(0); 422 | } 423 | }, 'xml'); 424 | }; 425 | [% END %] 426 | 427 | 428 | function find_pos( obj ) { 429 | 430 | var curtop = 0; 431 | 432 | if ( obj.offsetParent ) { 433 | 434 | do { 435 | curtop += obj.offsetTop; 436 | 437 | } while ( obj = obj.offsetParent ); 438 | 439 | return [ curtop ]; 440 | } 441 | } 442 | 443 | function show_error_tip( last_error_name, last_error_text ) { 444 | 445 | var error_x = ( mobilScreen ? 'inner-left' : 'left' ); 446 | var error_y = ( mobilScreen ? 'bottom' : 'center' ); 447 | var offset_x = ( mobilScreen ? 0 : 5 ); 448 | var offset_y = ( mobilScreen ? 5 : 0 ); 449 | 450 | $('#last_error_return').val(last_error_text + " (JS, " + last_error_name + ", step [% step %])"); 451 | 452 | if ( last_error_name == 'captha_div' ) { 453 | 454 | error_x = 'inner-left'; 455 | offset_x = ( mobilScreen ? 0 : 20 ); 456 | error_y = ( mobilScreen ? 'top' : 'center' ); 457 | offset_y = ( mobilScreen ? 50 : 0 ); 458 | } 459 | 460 | window.scroll( 0, find_pos( document.getElementById( last_error_name ) ) ); 461 | 462 | $( '#' + last_error_name ).poshytip({ 463 | className: 'tip-redsimple', 464 | content: last_error_text, 465 | showOn: 'none', 466 | alignTo: 'target', 467 | alignX: error_x, 468 | alignY: error_y, 469 | offsetX: offset_x, 470 | offsetY: offset_y, 471 | }); 472 | 473 | $( '#' + last_error_name ).bind({ 474 | 475 | click: function( e ) { 476 | 477 | $('#' + last_error_name ).poshytip( 'hide' ); 478 | } 479 | }); 480 | 481 | $( '#' + last_error_name ).poshytip( 'show' ); 482 | 483 | $( '.tip-redsimple .tip-inner' ).css( "font-size", ( mobilScreen ? '20px' : '' ) ); 484 | $( '.tip-redsimple .tip-inner' ).css( "line-height", ( mobilScreen ? '1.2' : '' ) ); 485 | 486 | if ( last_error_name == 'captha_div' ) { 487 | 488 | $( '.tip-redsimple' ).each( function() { 489 | 490 | $( this ).css( 'top', ( parseFloat( $( this ).css( 'top' ) ) + 38 ) ); 491 | }); 492 | } else { 493 | 494 | $( '#' + last_error_name ).css( { 'background-color' : '#FF9999', 'border-width' : '1px' } ); 495 | } 496 | 497 | return 1; 498 | } 499 | 500 | [% FOREACH post_index IN special.post_index %] 501 | 502 | $('#[% post_index %]').autocomplete({ 503 | 504 | source:function( request, response ) { 505 | 506 | $('#[% post_index %]').hide(); 507 | 508 | $('#[% post_index %]').parent().append( 509 | '' + $('#[% post_index %]').val() + 510 | ' ' 511 | ); 512 | 513 | $('#[% post_index %]_replacer').css( "font-size", ( mobilScreen ? '1.5em' : '' ) ); 514 | 515 | $.ajax({ 516 | url: "/autoform/findpcode.htm", 517 | 518 | dataType: "jsonp", 519 | 520 | data: { 521 | maxRows: 8, 522 | name_startsWith: request.term, 523 | center: [% appinfo.center %], 524 | }, 525 | 526 | success: function( data ) { 527 | 528 | $('#[% post_index %]').poshytip('hide'); 529 | 530 | $('#[% post_index %]_replacer').remove(); 531 | 532 | $('#[% post_index %]').show(); 533 | 534 | response( $.map( data.cmps, function( item ) { 535 | 536 | return { 537 | value: item.pcode, 538 | desc: item.cname, 539 | cdefault: item.cdefault, 540 | cid: item.cid 541 | } 542 | })); 543 | } 544 | }); 545 | }, 546 | 547 | delay:10, 548 | minLength:3, 549 | 550 | select: function( event, ui ) { 551 | 552 | $('#[% post_index %]').val( ui.item.value + ', ' + ui.item.desc ); 553 | 554 | return false; 555 | }, 556 | 557 | open: function(event, ui) { 558 | 559 | // $('#[% post_index %]').val( '' ); 560 | } 561 | }) 562 | .data( "autocomplete" )._renderItem = function( ul, item ) { 563 | 564 | return $( "
  • " ) 565 | .data( "item.autocomplete", item ) 566 | .append( "" + item.value + '
    ' + item.desc + "
    " ) 567 | .appendTo( ul ); 568 | }; 569 | [% END %] 570 | 571 | function check_all_inputs_errors() { 572 | 573 | var checks = [ 574 | [% FOREACH rule IN js_rules %] 575 | { 576 | [% FOREACH param IN rule %] 577 | [% param.key %]: '[% param.value %]', 578 | [% END %] 579 | }, 580 | [% END %] 581 | ]; 582 | 583 | var errors_num = 0; 584 | 585 | $('.input_gen, .select_gen,').poshytip('hide'); 586 | 587 | checks.forEach( function( field ) { 588 | 589 | $( '#' + field.name ).css( { 'background-color' : '' } ); 590 | 591 | if ( errors_num == 0 ) { 592 | 593 | errors_num += check_input( field.name, field.type, field.check, field.label ) || 0; 594 | } 595 | }); 596 | 597 | return errors_num; 598 | } 599 | 600 | function split_and_clarify( line ) { 601 | 602 | var symbol_err = { 603 | [% FOREACH s IN js_symbols %] 604 | '[% s.key %]': '[% s.value %]', 605 | [% END %] 606 | }; 607 | 608 | var symbols = line.split(""); 609 | var new_line_hash = {}; 610 | 611 | symbols.forEach( function(item, i) { 612 | new_line_hash[ symbol_err[ symbols[i] ] || symbols[i] ] = 1; 613 | }); 614 | 615 | var new_line_full = ''; 616 | 617 | for (var s in new_line_hash) { 618 | new_line_full += s + ', '; 619 | } 620 | 621 | var new_line = new_line_full.replace(/,\s$/, ''); 622 | 623 | return new_line; 624 | } 625 | 626 | function check_input( field, type, check, label ) { 627 | 628 | if ( ( field == '' ) || ( check == '' ) ) { 629 | return 0; 630 | } 631 | 632 | var val; 633 | 634 | if ( type == 'm_select' ) { 635 | val = $( '#' + field ).multipleSelect('getSelects'); 636 | } 637 | else { 638 | val = $( '#' + field ).val().replace(/^\s+|\s+$/g, ''); 639 | } 640 | 641 | [% IF special.sms_code %] 642 | 643 | if ( field == 'digital_signature') { 644 | 645 | var sms_code = CryptoJS.MD5( $('#digital_signature').val() ); 646 | 647 | var sms_check = '[% special.sms_code %]'; 648 | 649 | if ( sms_code != sms_check ) 650 | return show_error_tip( 'digital_signature', "[% langreq( 'Проверьте правильность введёного номера SMS' ) %]" ); 651 | } 652 | else 653 | [% END %] 654 | if ( type == 'input' ) { 655 | 656 | if ( /z/.test( check ) && ( val == '' ) ) { 657 | 658 | return show_error_tip( field, '[% langreq( js_errors.0 ) %]'.replace( /\[name\]/, label ) ); 659 | } 660 | 661 | if ( /D/.test( check ) ) { 662 | 663 | var date_reg = new RegExp( check.replace( /(z|D)/g, '' ) ); 664 | 665 | if ( !date_reg.test( val ) && ! (val == '') ) { 666 | 667 | return show_error_tip( field, '[% langreq( js_errors.1 ) %]'.replace( /\[name\]/, label ) ); 668 | } 669 | } 670 | else { 671 | var regexp = ''; 672 | 673 | if ( /W/.test( check ) ) { 674 | regexp += 'A-Za-z'; 675 | } 676 | if ( /Ё/.test( check ) ) { 677 | regexp += 'А-ЯЁа-яё'; 678 | } 679 | if ( /N/.test( check ) ) { 680 | regexp += '0-9'; 681 | } 682 | 683 | var regexp_add = check.replace( /(z|W|Ё|N)/g, '' ); 684 | 685 | var input_reg = new RegExp( '[^' + regexp + regexp_add + ']' ); 686 | 687 | var reverse_reg = new RegExp( '[' + regexp + regexp_add + ']', "g" ); 688 | 689 | if ( input_reg.test( val ) && ( val != '' ) ) { 690 | 691 | var symbols_incorrect = split_and_clarify( val.replace( reverse_reg, '' ) ); 692 | 693 | return show_error_tip( field, '[% langreq( js_errors.2 ) %]'.replace( /\[name\]/, label ) + 694 | ': ' + symbols_incorrect ); 695 | } 696 | } 697 | } 698 | else if ( type == 'checkbox' ) { 699 | 700 | if ( ( check == 'true' ) && ( !$( '#' + field ).is( ':checked' ) ) ) { 701 | 702 | return show_error_tip( field, '[% langreq( js_errors.3 ) %]'.replace( /\[name\]/, label ) ); 703 | } 704 | } 705 | else if ( type == 'checklist' ) { 706 | 707 | if ( ( check == 'at_least_one' ) && ( !$( 'input[name^=' + field + ']' ).is( ':checked' ) ) ) { 708 | 709 | return show_error_tip( field, '[% langreq( js_errors.11 ) %]'.replace( /\[name\]/, label ) ); 710 | } 711 | } 712 | else if ( type == 'radiolist' ) { 713 | 714 | if ( /z/.test( check ) && ( !$( 'input[name=' + field + ']' ).is( ':checked' ) ) ) { 715 | 716 | return show_error_tip( field, '[% langreq( js_errors.11 ) %]'.replace( /\[name\]/, label ) ); 717 | } 718 | } 719 | else if ( type == 'select' ) { 720 | 721 | if ( /z/.test( check ) && /^0$|^$/.test( $('select[name=' + field + ']').val() ) ) { 722 | 723 | return show_error_tip( field, '[% langreq( js_errors.3 ) %]'.replace( /\[name\]/, label ) ); 724 | } 725 | } 726 | else if ( type == 'm_select' ) { 727 | 728 | if ( /z/.test( check ) && /^0$|^$/.test( $('select[name=' + field + ']').multipleSelect('getSelects') ) ) { 729 | 730 | return show_error_tip( field, '[% langreq( js_errors.3 ) %]'.replace( /\[name\]/, label ) ); 731 | } 732 | } 733 | 734 | return 0; 735 | } 736 | --------------------------------------------------------------------------------