Revision 198
- Date:
- 2012/03/15 18:29:29
- Files:
-
- /utf8/plugins/webshop
- /utf8/plugins/webshop/comps
- /utf8/plugins/webshop/comps/contenido
- /utf8/plugins/webshop/comps/contenido/webshop
- /utf8/plugins/webshop/comps/contenido/webshop/autohandler (Diff) (Checkout)
- /utf8/plugins/webshop/comps/contenido/webshop/components
- /utf8/plugins/webshop/comps/contenido/webshop/components/block_order_status_changer.msn (Diff) (Checkout)
- /utf8/plugins/webshop/comps/contenido/webshop/components/object_form.msn (Diff) (Checkout)
- /utf8/plugins/webshop/comps/contenido/webshop/components/order_browse.msn (Diff) (Checkout)
- /utf8/plugins/webshop/comps/contenido/webshop/components/order_form.msn (Diff) (Checkout)
- /utf8/plugins/webshop/comps/contenido/webshop/components/order_list.msn (Diff) (Checkout)
- /utf8/plugins/webshop/comps/contenido/webshop/components/set_properties.msn (Diff) (Checkout)
- /utf8/plugins/webshop/comps/contenido/webshop/delivery.html (Diff) (Checkout)
- /utf8/plugins/webshop/comps/contenido/webshop/dhandler (Diff) (Checkout)
- /utf8/plugins/webshop/comps/contenido/webshop/facility.html (Diff) (Checkout)
- /utf8/plugins/webshop/comps/contenido/webshop/index.html (Diff) (Checkout)
- /utf8/plugins/webshop/comps/contenido/webshop/recount.html (Diff) (Checkout)
- /utf8/plugins/webshop/comps/contenido/webshop/subs
- /utf8/plugins/webshop/comps/contenido/webshop/subs/user_rights.msn (Diff) (Checkout)
- /utf8/plugins/webshop/comps/contenido/webshop/take_care.html (Diff) (Checkout)
- /utf8/plugins/webshop/config.proto (Diff) (Checkout)
- /utf8/plugins/webshop/lib
- /utf8/plugins/webshop/lib/webshop
- /utf8/plugins/webshop/lib/webshop/Address.pm (Diff) (Checkout)
- /utf8/plugins/webshop/lib/webshop/Apache.pm (Diff) (Checkout)
- /utf8/plugins/webshop/lib/webshop/Basket.pm (Diff) (Checkout)
- /utf8/plugins/webshop/lib/webshop/Delivery.pm (Diff) (Checkout)
- /utf8/plugins/webshop/lib/webshop/DeliverySection.pm (Diff) (Checkout)
- /utf8/plugins/webshop/lib/webshop/Init.pm (Diff) (Checkout)
- /utf8/plugins/webshop/lib/webshop/Keeper.pm (Diff) (Checkout)
- /utf8/plugins/webshop/lib/webshop/Order.pm (Diff) (Checkout)
- /utf8/plugins/webshop/lib/webshop/SQL
- /utf8/plugins/webshop/lib/webshop/SQL/AddressTable.pm (Diff) (Checkout)
- /utf8/plugins/webshop/lib/webshop/SQL/Basket.pm (Diff) (Checkout)
- /utf8/plugins/webshop/lib/webshop/SQL/Order.pm (Diff) (Checkout)
- /utf8/plugins/webshop/lib/webshop/State.pm.proto (Diff) (Checkout)
- /utf8/plugins/webshop/sql
- /utf8/plugins/webshop/sql/TOAST
- /utf8/plugins/webshop/sql/TOAST/adresses.sql (Diff) (Checkout)
- /utf8/plugins/webshop/sql/TOAST/basket.sql (Diff) (Checkout)
- /utf8/plugins/webshop/sql/TOAST/orders.sql (Diff) (Checkout)
Legend:
- Added
- Removed
- Modified
-
utf8/plugins/webshop/comps/contenido/webshop/autohandler
1 <%init> 2 3 $r->content_type('text/html'); 4 $m->call_next(); 5 6 </%init> -
utf8/plugins/webshop/comps/contenido/webshop/components/block_order_status_changer.msn
1 <fieldset> 2 <legend>Выбор заказов по статусу</legend> 3 4 <table width="100%" border="0" cellpadding="3" cellspacing="0" class="tlistdocs"> 5 <tr bgcolor="#efefef"> 6 <th align="center" width="1%">ID</th> 7 <th>Статус</th> 8 9 % foreach my $case ( @cases ) { 10 % next unless $case->[0]; 11 % my $style = $status && $case->[0] == $status ? 'inverted' : ''; 12 <tr class="<% $style %>"> 13 <td><% $case->[0] %></td> 14 <td><table cellpadding="0" cellspacing="0" border="0"> 15 <tr valign="top"> 16 <td width="10"> </td> 17 <td><a href="./?ost=<% $case->[0] %>"><% Encode::encode('utf-8', ucfirst(Encode::decode('utf-8',$case->[1]))) %></a></td> 18 </tr> 19 </table> 20 </td> 21 </tr> 22 % } 23 24 </table> 25 26 </fieldset> 27 <%args> 28 29 $status => undef 30 31 </%args> 32 <%init> 33 34 my ($prop) = grep { $_->{attr} eq 'status' } webshop::Order->new( $keeper->{webshop} )->structure; 35 my @cases = @{$prop->{cases}}; 36 37 </%init> -
utf8/plugins/webshop/comps/contenido/webshop/components/object_form.msn
1 <!-- Форма для редактирования объекта --> 2 <a name="top"></a> 3 <form enctype="multipart/form-data" action="<% $PROTOS->{$proto}->[1] %>" method="POST" name="form" onSubmit="javascript:Save()"> 4 <table border="0" width="100%" cellspacing="0" cellpadding="6"> 5 <tr> 6 <td style="font-size:110%;"> 7 <b><% (ref($object) && $object->id() ) ? 'Редактирование' : 'Создание' %> <% $PROTOS->{$proto}->[0] %> типа "<% $object->class_name() %>"</b> 8 </td> 9 <td align="right"> 10 % unless ( $proto eq 'sections' && $object->id == 1 ) { 11 <input type="submit" value="Сохранить" class="input_btn"> 12 % if (( $proto eq 'documents' ) || ( $proto eq 'sections' )) { 13 <input type="submit" name="_save_and_leave" value="Сохранить и выйти" class="input_btn"> 14 <input type="submit" name="_save_and_again" value="Сохранить и создать новый" class="input_btn"> 15 % } 16 % } 17 </td> 18 </tr> 19 </table> 20 21 % if ( $m->comp_exists ('/contenido/components/object_context_menu.msn') ) { 22 <div style="text-align:right;"><& '/contenido/components/object_context_menu.msn', object => $object &></div> 23 % } 24 25 <center> 26 <table width="100%" cellpadding="0" cellspacing="0" border="0"> 27 <tr> 28 <td bgcolor="#999999"> 29 <table width="100%" cellpadding="0" cellspacing="1" border="0"> 30 <tr><td valign="top" width="80%" bgcolor="#ffffff"> 31 <center> 32 <table width="98%" cellpadding="1" cellspacing="0" border="0"> 33 34 <%perl> 35 36 my @properties = $object->structure(); 37 38 for (0..$#properties) 39 { 40 41 my $prop = $properties[$_]; 42 next if ($prop->{hidden} == 1) || ($prop->{type} eq 'image') || ($prop->{type} eq 'external') || ($prop->{type} =~ /^array/i) || ($prop->{type} =~ /^image/) || ($prop->{type} eq 'multimedia') || ($prop->{type} eq 'multimedia_new') || ($prop->{type} eq 'audio'); 43 44 </%perl> 45 <tr><td height="8"></td></tr> 46 <tr><td nowrap> 47 <table cellpadding="0" cellspacing="0" border="0"> 48 <tr> 49 % if( ( $prop->{type} eq 'flag' ) || ($prop->{type} eq 'checkbox') ) 50 % { 51 <td><& "/contenido/components/inputs/checkbox.msn", prop => $prop, object=>$object, options=>$options, name => $prop->{attr}, check => $object->{$prop->{attr}}, id => $object->id() &></td> 52 % } 53 <td nowrap><b><% $prop->{rusname} %></b> /</td> 54 <td align="right" nowrap><font color="#888888" size="-1"> name="<% $prop->{attr} %>"</font></td> 55 % if( $prop->{readonly} ) 56 % { 57 <td align="right" nowrap> / <font color="#CC0000" size="-1">Значение нельзя изменить</font></td> 58 % } 59 </tr> 60 </table> 61 </td></tr> 62 % if ($prop->{type} eq 'parent') 63 % { 64 <tr><td><& "/contenido/components/inputs/$prop->{type}.msn", prop => $prop, object=>$object, options=>$options, name => $prop->{attr}, check => ($object->{$prop->{attr} } || $prop->{default} || $sect_id ), id => $object->id() &></td></tr> 65 % } 66 % elsif( ( $prop->{type} ne 'flag' ) && ($prop->{type} ne 'checkbox') ) 67 % { 68 <tr><td><& "/contenido/components/inputs/$prop->{type}.msn", prop => $prop, object=>$object, options => $options, name => $prop->{attr}, check => $object->{$prop->{attr}}, id => ($object->id() || 0) &></td></tr> 69 % } 70 % } 71 <tr> 72 <td><br> 73 74 % for (0..$#properties) 75 % { 76 % my $prop = $properties[$_]; 77 % next if ($prop->{hidden} != 1); 78 % next if ($prop->{attr} eq 'id' && $clone); 79 <input type="hidden" name="<% $prop->{attr} %>" value="<% html_escape($object->{ $prop->{attr} }) %>"> 80 % } 81 <input type="hidden" name="sect_id" value="<% $sect_id %>"> 82 %#если класса в свойствах обьекта нет все равно надо его пробросить как hidden 83 % unless (grep {$_->{attr} eq 'class'} @properties) { 84 <input type="hidden" name="class" value="<% html_escape($object->{class}) %>"> 85 % } 86 % if ( $clone ) { 87 <input type="hidden" name="clone" value="<% $object->id %>"> 88 % } 89 <input type="hidden" name="save" value="1"> 90 91 </td> 92 </tr> 93 </table> 94 </center> 95 96 </td> 97 <td valign="top" bgcolor="#efefef"> 98 <div style="width:270px"><spacer type="block" width="270"></div> 99 <div><iframe name="DocFinder" id="DocFinder" src="/contenido/find_document.html" frameborder="0" 100 marginheight="0" marginwidth="0" width="100%" height="0"></iframe></div> 101 <table cellpadding="5" cellspacing="0" border="0"><tr><td> 102 <p><font size=+1><b><nobr>Мультимедиа-объекты</nobr> к <% $PROTOS->{$proto}->[2] %></b></font></p> 103 104 % for (0..$#properties) 105 % { 106 % my $prop = $properties[$_]; 107 % 108 % if ($prop->{type} eq 'image') 109 % { 110 % my $IMAGE = $object->get_image( $prop->{attr} ); 111 % if (ref($IMAGE) ne 'HASH') { next }; 112 <& "/contenido/components/inputs/image.msn", 113 IMAGE => $IMAGE, 114 rusname => $prop->{rusname}, 115 prop => $prop, object=>$object, 116 attr => $prop->{attr}, 117 options => $options, 118 &> 119 120 % } elsif ($prop->{type} eq 'images') 121 % { 122 % my $IMAGES = $object->get_image( $prop->{attr} ); 123 % if (ref($IMAGES) ne 'HASH') { next }; 124 % my $MN = $IMAGES->{maxnumber}+0; 125 % for my $mn (1..$MN) 126 % { 127 % my $IMAGE = $IMAGES->{'image_'.$mn}; 128 129 <& "/contenido/components/inputs/image.msn", 130 rusname => $prop->{rusname}, 131 prop => $prop, object=>$object, 132 attr => $prop->{attr}.'_'.$mn, 133 IMAGE => $IMAGE, 134 options => $options, 135 &> 136 137 % } 138 % my $ME = exists $prop->{empty_slots} ? $prop->{empty_slots} : 5; 139 % $ME = ($ME + $IMAGES->{maxnumber}) >= 100 ? 0 : (100 - $IMAGES->{maxnumber} < $ME ? 100 - $IMAGES->{maxnumber} : $ME ); 140 % for my $mn (1..$ME) 141 % { 142 143 144 <& "/contenido/components/inputs/image.msn", 145 IMAGE => {}, 146 rusname => $prop->{rusname}, 147 prop => $prop, object=>$object, 148 attr => $prop->{attr}.'_'.($MN+$mn), 149 options => $options, 150 &> 151 152 % } 153 % } elsif ($prop->{type} eq 'multimedia') 154 % { 155 % my $MULTI = $object->get_image( $prop->{attr} ); 156 157 <& "/contenido/components/inputs/multimedia.msn", 158 rusname => $prop->{rusname}, 159 prop => $prop, object=>$object, 160 attr => $prop->{attr}, 161 MULTI => $MULTI, 162 options => $options, 163 &> 164 % } elsif ($prop->{type} eq 'multimedia_new') 165 % { 166 % my $MULTI = $object->get_image( $prop->{attr} ); 167 168 <& "/contenido/components/inputs/multimedia_new.msn", 169 rusname => $prop->{rusname}, 170 prop => $prop, object=>$object, 171 attr => $prop->{attr}, 172 MULTI => $MULTI, 173 options => $options, 174 &> 175 % } elsif ($prop->{type} eq 'audio') 176 % { 177 % my $MULTI = $object->get_image( $prop->{attr} ); 178 179 <& "/contenido/components/inputs/audio.msn", 180 rusname => $prop->{rusname}, 181 prop => $prop, object=>$object, 182 attr => $prop->{attr}, 183 MULTI => $MULTI, 184 options => $options, 185 &> 186 % } 187 % } 188 189 </table> 190 </td></tr></table> 191 192 193 </td></tr> 194 </table> 195 196 </td></tr></table> 197 </center> 198 199 <script> 200 <!-- 201 function updateList(theFild,value,text) { 202 for (var i = 0; i < theFild.options.length; i++) { 203 if (theFild.options[i].value == value) { 204 return false; 205 } 206 } 207 var option_length = theFild.options.length++; 208 eval("theFild.options[option_length].value=value"); 209 eval("theFild.options[option_length].text=text"); 210 211 Save(); this.form.submit(); 212 213 } 214 //--> 215 </script> 216 217 % unless ( $proto eq 'sections' && $object->id == 1 ) { 218 <div align="center"><input type="submit" value="Сохранить" class="input_btn"> 219 %# <input type="submit" value="Сохранить изменения в <% $PROTOS->{$proto}->[3] %>" class="input_btn"> 220 221 %# 222 %# Как же сохранять эти гребанные связи? 223 %# onClick="javascript:updateList(parent.opener.links.links,'link_6_20_DefaultLink','test');" 224 %# 225 226 227 % if ($object->id > 0 && !$clone) { 228 <input name="delete" type="button" value="Удалить" onClick="javascript:window.location='confirm.html?id=<% $object->id() %>&action=<% $proto %>_deletion&class=<% $object->class() %>'" class="input_btn">\ 229 % } 230 % if ( ref $filter_params eq 'HASH' ) { 231 % while ( my ($key, $value) = each %$filter_params ) { 232 % next if grep { $_->{attr} eq $key } $object->structure(); 233 <input type="hidden" name="<% $key %>" value="<% $value %>"> 234 % } 235 % } 236 <input type="hidden" name="control_charset" value="Контроль"> 237 % if (( $proto eq 'documents' ) || ( $proto eq 'sections' )) { 238 <input type="submit" name="_save_and_leave" value="Сохранить и выйти" class="input_btn"> 239 % unless ( $clone ) { 240 <input type="submit" name="_save_and_again" value="Сохранить и создать новый" class="input_btn"> 241 % } 242 % } 243 </div> 244 % } 245 </form> 246 247 <%ARGS> 248 249 $proto => 'documents' 250 $object => undef 251 $clone => undef 252 $sect_id => 1 253 $filter_params => undef 254 255 </%ARGS> 256 257 <%ONCE> 258 my $PROTOS = { 259 'documents' => ['документа','document.html','документу','документе'], 260 'sections' => ['секции','section.html','секции','секции'], 261 'links' => ['связи','link.html','связи','связи'], 262 'users' => ['пользователя','users.html','пользователю','пользователе'], 263 }; 264 </%ONCE> 265 266 <%INIT> 267 return undef unless ref($object); 268 269 my $toopi = $project->$proto(); 270 my $options = {}; 271 if ($toopi && (ref($toopi) eq 'HASH') && (exists($toopi->{ $object->class }))) { 272 %{ $options } = %{ $toopi->{ $object->class } }; 273 } 274 </%INIT> -
utf8/plugins/webshop/comps/contenido/webshop/components/order_browse.msn
1 <script type="text/javascript"> 2 <!-- 3 var aIDs = new Array (<% scalar @$documents ? join (',', map { $_->id } @$documents) : '' %>); 4 function delete_check () { 5 for ( var i = 0; i < aIDs.length; i++ ) { 6 var sFieldName = 'delete_' + aIDs[i] + '_id'; 7 var oField = document.forms['section_browse'].elements[sFieldName]; 8 if ( oField.checked ) { 9 oField.checked = 0; 10 } else { 11 oField.checked = 1; 12 } 13 } 14 } 15 //--> 16 </script> 17 <form name="section_browse" action="./" method="POST"> 18 <table width="100%" border="0" cellpadding="4" cellspacing="0" class="tlistdocs"> 19 <tr bgcolor="#efefef"> 20 <th><a href="javascript:delete_check()" onclick="delete_check(); return false;"><img src="/contenido/i/actions/delete.gif" width="14" height="17" alt="Удаление документов" align="absmiddle" border="0" hspace="1"></a></th> 21 % 22 % foreach (@$columns) { 23 <th><% $_->{shortname} || $_->{rusname} %></th> 24 % } 25 % 26 </tr> 27 % 28 % unless (@$documents) { 29 <tr><td align="center" colspan="<% scalar @$columns %>">Документы не найдены</td></tr> 30 % } 31 % foreach my $document (@$documents) { 32 % 33 % next unless ref($document); 34 % my $document_access = $user->section_accesses($user, $document->section); 35 % 36 <tr valign="top"> 37 <td nowrap>\ 38 % if ($document_access == 2) { 39 % $delete_status = 1; 40 <input type="checkbox" name="<% 'delete_'.$document->id.'_id' %>"> 41 % } else { 42 43 % } 44 </td> 45 % 46 % for my $col (@$columns) { 47 % if ($col->{attr} eq 'dtime') { 48 % 49 <td nowrap><& "/contenido/components/show_dtime.msn", dtime=>$document->{dtime} &>\ 50 % if ($document->{ctime} ne $document->{mtime}) { 51 % my $colortime = '#c66'; 52 <div style="color:<% $colortime %>;"><& "/contenido/components/show_dtime.msn", dtime=>$document->{mtime} &></div>\ 53 % } 54 % 55 % } elsif ($col->{attr} eq 'name') { 56 % my $style = $document->contenido_status_style ? ' style="'.$document->contenido_status_style.'"' : ''; 57 % my ($a1, $a2) = $href ? ('<a href="./'.$href.'?id='.$document->id.($params_unclassed ? '&'.$params_unclassed : '').'"'.$style.'>','</a>') : ('',''); 58 <td><span<% $style %> class="<% $document->status ? '':'hiddensect' %>">\ 59 % 60 % my $name=$document->name ? $document->name : 'Безымянный документ N'.$document->id; 61 <% $a1 %><% $name | h %><% $a2 %>\ 62 % 63 </span>\ 64 % 65 % } elsif ($col->{attr} eq 'id') { 66 % 67 <td><span class="<% $document->status ? '':'hiddensect' %>">\ 68 % if ($document_access == 2) { 69 <a href="document.html?id=<% $document->id %>&class=<% $document->class %><% $params_unclassed ? '&'.$params_unclassed : '' %>"><% $document->id %> </a>\ 70 % } else { 71 <% $document->id %> \ 72 % } 73 </span>\ 74 % 75 % } elsif ( exists $col->{inline} && $col->{inline} ) { 76 % $inline_status = 1; 77 % my $attr = $col->{attr}; 78 % if ( $col->{type} =~ /^(string|integer|float)$/ && $col->{inline} ) { 79 % my $style = $col->{inline_style} ? $col->{inline_style} : ($col->{type} =~ /^(integer|float)$/ ? 'text-align:right; ' : '' ); 80 <td><input type="text" name="<% 'update_'.$document->id.'_'.$attr %>" value="<% $document->$attr %>" style="<% $col->{inline_width} ? 'width:'.$col->{inline_width}.'px;' : 'width:65px; ' %> <% $col->{inline_style} || '' %>"> 81 % } elsif ($col->{type} eq 'checkbox') { 82 % my $checked = $document->$attr ? ' checked' : ''; 83 <td align="center"><input type="checkbox" name="<% 'update_'.$document->id.'_'.$attr %>"<% $checked %>> 84 % } elsif ($col->{type} eq 'select') { 85 % my $options = {}; 86 % if ($toopi && (ref($toopi) eq 'HASH') && (exists($toopi->{$document->class}))) { 87 % %{ $options } = %{ $toopi->{$document->class} }; 88 % } 89 % my $values = $options->{$col->{attr}}; 90 <td><select name="<% 'update_'.$document->id.'_'.$attr %>"> 91 % if ( ref $values eq 'ARRAY' ) { 92 % foreach my $val ( @$values ) { 93 % my $selected = $val eq $document->$attr ? ' selected' : ''; 94 <option value="<% $val %>"<% $selected %>><% $val %> 95 % } 96 % } 97 </select> 98 % } elsif ($col->{type} eq 'status') { 99 % my $cases = $col->{cases}; 100 % if ( ref $cases eq 'ARRAY' ) { 101 <td><select name="<% 'update_'.$document->id.'_'.$attr %>" style="<% $col->{inline_width} ? 'width:'.$col->{inline_width}.'px;' : '' %> <% $col->{inline_style} || '' %>"> 102 % foreach my $case ( @$cases ) { 103 % my $selected = $case->[0] eq $document->$attr ? ' selected' : ''; 104 <option value="<% $case->[0] %>"<% $selected %>><% $case->[1] %> 105 % } 106 </select> 107 % } 108 % } 109 % 110 % } elsif ($col->{attr} eq 'class') { 111 % 112 <td><% $document->class_name %> <font color="#999999">(<% $document->class %>)</font>\ 113 % 114 % } elsif ($col->{type} eq 'datetime') { 115 % 116 <td nowrap><& "/contenido/components/show_dtime.msn", dtime=>$document->{$col->{attr}} &>\ 117 % 118 % } elsif ($col->{attr} eq '_act_') { 119 % my $actions; 120 % if ( $document->$user_id == $user->id ) { 121 % $actions = join (' | ', map { '<a href="./'.$_->{href}.'?id='.$document->id.($params_unclassed ? '&'.$params_unclassed : '').'">'.$_->{name}.'</a>' } @actions); 122 % } else { 123 % my $profile = exists $users{$document->$user_id} ? $users{$document->$user_id} : undef; 124 % unless ( ref $profile ) { 125 % $profile = $keeper->get_user_by_id( $document->$user_id ); 126 % $users{$profile->id} = $profile if ref $profile; 127 % } 128 % if ( ref $profile ) { 129 % $actions = $profile->name; 130 % } else { 131 % $actions = join (' | ', map { '<a href="./'.$_->{href}.'?id='.$document->id.($params_unclassed ? '&'.$params_unclassed : '').'">'.$_->{name}.'</a>' } @actions); 132 % } 133 % } 134 <td nowrap><% $actions %>\ 135 % if ( $inline_status ) { 136 <input type="hidden" name="update_<% $document->id %>_class" value="<% $document->class %>"> 137 % } 138 % if ( $delete_status ) { 139 <input type="hidden" name="delete_<% $document->id %>_class" value="<% $document->class %>"> 140 % } 141 % 142 % } else { 143 % 144 % if ($col->{type} eq 'date') { 145 % my $date=$document->{$col->{attr}}; 146 % $date=~/(\d{4}-\d{2}-\d{2})/; 147 <td nowrap align="right"><% $1 || ' ' %>\ 148 % } elsif ($col->{type} eq 'datetime') { 149 <td nowrap align="right"><% $document->{$col->{attr}} || ' ' %>\ 150 % } elsif ($col->{type} eq 'integer') { 151 <td align="right"><% $document->{$col->{attr}} %> \ 152 % } elsif ($col->{type} eq 'lookup') { 153 <td align="left">\ 154 % my $id = $document->{$col->{attr}}; 155 % if ($id) { 156 % my ($doc)=$keeper->get_documents( ( ref($col->{lookup_opts}) ? %{$col->{lookup_opts}} : () ), id=>$id); 157 % if ($doc) { 158 <a href="document.html?id=<% $doc->id %>&class=<% $doc->class %><% $params_unclassed ? '&'.$params_unclassed : '' %>"><% $doc->name || $doc->id %></a> \ 159 % } else { 160 <span class="hiddensect"><% $document->{$col->{attr}} %>???</span>\ 161 % } 162 % } else { 163 <span class="hiddensect">NULL</span>\ 164 % } 165 % } elsif ($col->{type} eq 'status') { 166 % my $status_map = ref $col->{cases} eq 'ARRAY' ? $col->{cases} : $keeper->default_status(); 167 % my ($doc_status) = grep { $_->[0] eq $document->{$col->{attr}} } @$status_map; 168 % $doc_status ||= [$document->{$col->{attr}}, 'Неизвестный']; 169 <td nowrap><% $doc_status->[1].'('.$doc_status->[0].')' %>\ 170 % } else { 171 <td><% defined($document->{$col->{attr}}) ? $document->{$col->{attr}} : ' ' %>\ 172 % } 173 % } 174 </td> 175 % 176 % } #- for @columns 177 % 178 </tr> 179 % } #- foreach @documents 180 </table> 181 % if ( ref $filter eq 'HASH' ) { 182 % while ( my ($key, $value) = each %$filter ) { 183 % next if $key eq 's'; 184 <input type="hidden" name="<% $key %>" value="<% $value |h %>"> 185 % } 186 % } 187 % if ( $inline_status || $delete_status ) { 188 <div style="text-align:right; padding:10px 0;"> 189 % if ( $inline_status ) { 190 <input type="submit" name="update" value="Сохранить изменения" class="input_btn"> 191 % } 192 % if ( $delete_status ) { 193 <input type="submit" name="delete" value="Удалить выбранные" class="input_btn" onclick="return confirm('Все отмеченные позиции будут удалены');"> 194 % } 195 </div> 196 % } 197 </form> 198 <%args> 199 200 $section => undef 201 $documents => undef 202 $columns => undef 203 $id => undef 204 $filter => undef 205 $status => undef 206 207 </%args> 208 <%init> 209 210 return unless ref $documents eq 'ARRAY'; 211 return unless ref $columns eq 'ARRAY'; 212 213 @$columns = grep { $_->{attr} ne 'status' } @$columns; 214 my $toopi = $project->documents(); 215 my $inline_status = 0; 216 my $delete_status = 0; 217 my $params = ref $filter eq 'HASH' ? join ('&', map { $_.'='.$filter->{$_} } keys %$filter ) : ''; 218 my $params_unclassed = ref $filter eq 'HASH' ? join ('&', map { $_.'='.$filter->{$_} } grep { $_ ne 'class' } keys %$filter ) : ''; 219 my $params_unsection = ref $filter eq 'HASH' ? join ('&', map { $_.'='.$filter->{$_} } grep { $_ ne 's' } keys %$filter ) : ''; 220 221 my $active_rights = $m->comp('/contenido/webshop/subs/user_rights.msn'); 222 223 my %users; 224 my ($href, @actions, $user_id); 225 if ( $status == 1 && (!$active_rights || $active_rights == 1) ) { 226 $href = 'take_care.html'; 227 @actions = { href => $href, name => 'обработать' }; 228 $user_id = 'manager_id'; 229 } elsif ( $status == 2 && (!$active_rights || $active_rights == 2) ) { 230 $href = 'facility.html'; 231 @actions = { href => $href, name => 'собрать' }; 232 $user_id = 'vault_id'; 233 } elsif ( $status == 3 && (!$active_rights || $active_rights == 3) ) { 234 $href = 'delivery.html'; 235 @actions = { href => $href, name => 'доставить' }; 236 $user_id = 'postman_id'; 237 } elsif ( $status == 4 && !$active_rights ) { 238 $href = 'delivery.html'; 239 @actions = { href => $href, name => 'просмотр' }; 240 } 241 242 </%init> -
utf8/plugins/webshop/comps/contenido/webshop/components/order_form.msn
1 <!-- Форма для редактирования объекта --> 2 <a name="top"></a> 3 % if ( $context eq 'facil' ) { 4 <b style="font-size:110%">Комплектация ЗАКАЗА</b> 5 % } elsif ( $context eq 'post' ) { 6 <b style="font-size:110%">Доставка ЗАКАЗА</b> 7 % } else { 8 <b style="font-size:110%">Просмотр и редактирование ЗАКАЗА</b> 9 % } 10 <center> 11 <table width="100%" cellpadding="0" cellspacing="0" border="0"> 12 <tr> 13 <td bgcolor="#999999"> 14 15 16 <table width="100%" cellpadding="0" cellspacing="1" border="0"> 17 <tr><td valign="top" width="50%" bgcolor="#ffffff"> 18 19 <form enctype="multipart/form-data" action="<% $action %>" method="POST" name="form" onSubmit="javascript:Save()"> 20 21 <table border="0" width="100%" cellspacing="0" cellpadding="6"> 22 <tr> 23 <td align="right"> 24 <input type="submit" value="Сохранить" class="input_btn"> 25 <input type="submit" name="_save_and_leave" value="Сохранить и выйти" class="input_btn"> 26 <input type="submit" name="delete" value="Отменить" onClick="return confirm('Отменить заказ?');" class="input_btn"><br> 27 % if ( $context eq 'facil' ) { 28 <input type="submit" name="_ret_manager" value="Вернуть менеджеру" class="input_btn"> 29 <input type="submit" name="_save_and_deliver" value="Отправить в доставку" class="input_btn"> 30 % } elsif ( $context eq 'post' ) { 31 <input type="submit" name="_ret_manager" value="Вернуть менеджеру" class="input_btn"> 32 <input type="submit" name="_ret_facility" value="Вернуть в доставку" class="input_btn"> 33 <input type="submit" name="_save_and_deliver" value="Отметка о доставке" class="input_btn"> 34 % } else { 35 <input type="submit" name="_save_and_complect" value="На комплектацию" class="input_btn"> 36 <input type="submit" name="_save_and_deliver" value="Сразу в доставку" class="input_btn"> 37 % } 38 39 <input type="hidden" name="control_charset" value="Контроль"> 40 % if ( ref $filter_params eq 'HASH' ) { 41 % while ( my ($key, $value) = each %$filter_params ) { 42 % next if grep { $_->{attr} eq $key } $object->structure(); 43 <input type="hidden" name="<% $key %>" value="<% $value %>"> 44 % } 45 % } 46 </td> 47 </tr> 48 </table> 49 50 <center> 51 <table width="98%" cellpadding="1" cellspacing="0" border="0"> 52 53 <%perl> 54 55 my @properties = $object->structure(); 56 57 for (0..$#properties) 58 { 59 60 my $prop = $properties[$_]; 61 my $field = $prop->{attr}; 62 next if ($prop->{hidden} == 1) || ($prop->{type} eq 'external'); 63 if ( $context eq 'facil' ) { 64 next unless $prop->{$context.'show'} || $prop->{$context."edit"}; 65 } elsif ( $context eq 'post' ) { 66 next unless $prop->{$context.'show'} || $prop->{$context."edit"}; 67 } else { 68 next if $prop->{manager_hidden}; 69 } 70 71 </%perl> 72 <tr><td height="8"></td></tr> 73 <tr><td nowrap> 74 <table cellpadding="0" cellspacing="0" border="0"> 75 <tr> 76 % if( ( $prop->{type} eq 'flag' ) || ($prop->{type} eq 'checkbox') ) { 77 <td><& "/contenido/components/inputs/checkbox.msn", prop => $prop, object=>$object, options=>$options, name => $prop->{attr}, check => $object->{$prop->{attr}}, id => $object->id() &></td> 78 % } 79 <td nowrap><b><% $prop->{rusname} %></b> /</td> 80 <td align="right" nowrap><font color="#888888" size="-1"> name="<% $prop->{attr} %>"</font></td> 81 % if( $prop->{readonly} ) { 82 <td align="right" nowrap> / <font color="#CC0000" size="-1">Значение нельзя изменить</font></td> 83 % } 84 </tr> 85 </table> 86 </td></tr> 87 % if ( ($context && $prop->{$context.'show'}) || $prop->{manshow} ) { 88 % if ( exists $prop->{lookup_opts} ) { 89 % my $doc = $keeper->get_document_by_id( $object->$field, class => $prop->{lookup_opts}{class} ); 90 <tr><td><% $doc->name %></td></tr> 91 % } elsif ( $prop->{type} eq 'status' ) { 92 % my ($case) = grep { $_->[0] == $object->$field } @{$prop->{cases}}; 93 <tr><td><% ref $case ? $case->[1] : '<span style="color:red;">Значение: '.$object->$field.'</span>' %></td></tr> 94 % } else { 95 <tr><td><% $object->$field %></td></tr> 96 % } 97 % } else { 98 % if ($prop->{type} eq 'parent') { 99 <tr><td><& "/contenido/components/inputs/$prop->{type}.msn", prop => $prop, object=>$object, options=>$options, name => $prop->{attr}, check => ($object->{$prop->{attr} } || $prop->{default} || $sect_id ), id => $object->id() &></td></tr> 100 % } elsif( ( $prop->{type} ne 'flag' ) && ($prop->{type} ne 'checkbox') ) { 101 <tr><td><& "/contenido/components/inputs/$prop->{type}.msn", prop => $prop, object=>$object, options => $options, name => $prop->{attr}, check => $object->{$prop->{attr}}, id => ($object->id() || 0) &></td></tr> 102 % } 103 % } 104 % } 105 <tr> 106 <td><br> 107 108 % for (0..$#properties) { 109 % my $prop = $properties[$_]; 110 % next if ($prop->{hidden} != 1); 111 <input type="hidden" name="<% $prop->{attr} %>" value="<% html_escape($object->{ $prop->{attr} }) %>"> 112 % } 113 <input type="hidden" name="sect_id" value="<% $sect_id %>"> 114 %#если класса в свойствах обьекта нет все равно надо его пробросить как hidden 115 % unless (grep {$_->{attr} eq 'class'} @properties) { 116 <input type="hidden" name="class" value="<% html_escape($object->{class}) %>"> 117 % } 118 <input type="hidden" name="save" value="1"> 119 120 </td> 121 </tr> 122 </table> 123 </center> 124 125 </form> 126 127 </td> 128 <td valign="top" bgcolor="white" width="50%"> 129 <% spacer(w=>270) %> 130 <div><iframe name="DocFinder" id="DocFinder" src="/contenido/find_document.html" frameborder="0" 131 marginheight="0" marginwidth="0" width="100%" height="0"></iframe></div> 132 <table width="100%" cellpadding="5" cellspacing="0" border="0"><tr><td> 133 <p><font size=+1><b><nobr>Список позиций в заказе:</nobr></b></font></p> 134 135 136 <& /contenido/webshop/components/order_list.msn, order => $object, filter_params => $filter_params, context => $context &> 137 138 139 140 </table> 141 </td></tr></table> 142 143 144 </td></tr> 145 </table> 146 147 </td></tr></table> 148 </center> 149 150 <script> 151 <!-- 152 function updateList(theFild,value,text) { 153 for (var i = 0; i < theFild.options.length; i++) { 154 if (theFild.options[i].value == value) { 155 return false; 156 } 157 } 158 var option_length = theFild.options.length++; 159 eval("theFild.options[option_length].value=value"); 160 eval("theFild.options[option_length].text=text"); 161 162 Save(); this.form.submit(); 163 164 } 165 //--> 166 </script> 167 168 169 <%ARGS> 170 171 $proto => 'documents' 172 $object => undef 173 $context => undef 174 $sect_id => 1 175 $filter_params => undef 176 177 </%ARGS> 178 179 <%ONCE> 180 my $PROTOS = { 181 'documents' => ['документа','document.html','документу','документе'], 182 'sections' => ['секции','section.html','секции','секции'], 183 'links' => ['связи','link.html','связи','связи'], 184 'users' => ['пользователя','users.html','пользователю','пользователе'], 185 }; 186 </%ONCE> 187 188 <%INIT> 189 return undef unless ref($object); 190 191 my $action = $context eq 'facil' ? 'facility.html' : $context eq 'post' ? 'delivery.html' : 'take_care.html'; 192 my $toopi = $project->$proto(); 193 my $options = {}; 194 if ($toopi && (ref($toopi) eq 'HASH') && (exists($toopi->{ $object->class }))) { 195 %{ $options } = %{ $toopi->{ $object->class } }; 196 } 197 </%INIT> -
utf8/plugins/webshop/comps/contenido/webshop/components/order_list.msn
1 <style> 2 3 .number { text-align:right; padding-right:5px; } 4 .blue { color:blue; } 5 input.text { border:1px solid gray; } 6 7 </style> 8 % if ( @basket ) { 9 <form action="recount.html" method="post"> 10 <table width="100%" border="0" cellpadding="4" cellspacing="0" class="tlistdocs" bgcolor="white"> 11 <tr bgcolor="#efefef"> 12 <th><% $context ? ' ' : '<img src="/contenido/i/actions/delete.gif">' %></th> 13 <th>Артикул</th> 14 <th>Название</th> 15 <th>Цвет</th> 16 <th>Цена</th> 17 <th>Кол-во</th> 18 <th>Сумма</th> 19 </tr> 20 21 % foreach my $obj ( @basket ) { 22 % $total_num += $obj->number; 23 % $total_sum += $obj->number * $obj->price; 24 <tr><td>\ 25 % if ( $context ) { 26 \ 27 % } else { 28 <input type="checkbox" name="delete" value="<% $obj->id %>">\ 29 % } 30 </td> 31 <td><% $obj->articul %></td> 32 <td><% $obj->name %></td> 33 <td><% $obj->colour %></td> 34 % if ( $context ) { 35 <td class="number"><% $obj->price %></td> 36 <td class="number"><% $obj->number %></td> 37 % } else { 38 <td class="number"><input type="text" class="text number" size="8" name="item_<% $obj->id %>.price" value="<% $obj->price %>"></td> 39 <td class="number"><input type="text" class="text number" size="5" name="item_<% $obj->id %>.num" value="<% $obj->number %>"></td> 40 % } 41 <td class="number"><% $obj->number * $obj->price %></td> 42 </tr> 43 % } 44 45 <tr> 46 <td colspan="5" align="right"><b>Итого товаров</b></td> 47 <td class="number"><b class="blue"><% $total_num %></b></td> 48 <td class="number"><b class="blue"><% $total_sum %></b></td> 49 </tr> 50 <tr> 51 <td colspan="5" align="right"><b>Доставка</b></td> 52 <td class="number" colspan="2"><b class="blue"><% $order->sum_delivery %></b></td> 53 </tr> 54 <tr> 55 <td colspan="5" align="right"><b>Итого с доставкой</b></td> 56 <td class="number" colspan="2"><b class="blue"><% $total_sum + ($order->sum_delivery || 0) %></b></td> 57 </tr> 58 59 </table> 60 % unless ( $context ) { 61 <div class="number"><input type="submit" name="update" value="Пересчитать" class="input_btn"></div> 62 % } 63 % if ( ref $filter_params eq 'HASH' ) { 64 % while ( my ($key, $value) = each %$filter_params ) { 65 % next if grep { $_->{attr} eq $key } $order->structure(); 66 <input type="hidden" name="<% $key %>" value="<% $value %>"> 67 % } 68 % } 69 <input type="hidden" name="id" value="<% $order->id %>"> 70 71 72 </form> 73 % } else { 74 <div style="color:red; font-size:110%; margin:20px 0;">Заказ пустой</div> 75 % } 76 <%args> 77 78 $order => undef 79 $filter_params => undef 80 $context => undef 81 82 </%args> 83 <%init> 84 85 return unless ref $order; 86 my @basket = $keeper->get_documents( 87 class => 'webshop::Basket', 88 status => 1, 89 order_id => $order->id, 90 ); 91 my $total_sum = 0; 92 my $total_num = 0; 93 94 </%init> -
utf8/plugins/webshop/comps/contenido/webshop/components/set_properties.msn
1 <%ARGS> 2 3 $object => undef 4 $SETS => undef 5 $context=> undef 6 7 </%ARGS> 8 <%INIT> 9 10 use Contenido::File; 11 use vars qw($keeper $request ); 12 13 $request->{local_codepage} = 'UTF8'; 14 $request->{local_codepage} = 'WIN' if Convert::Cyrillic::cstocs('WIN', 'UTF8', $SETS->{control_charset}) eq 'Контроль'; 15 $request->{local_codepage} = 'KOI8' if Convert::Cyrillic::cstocs('KOI8', 'UTF8', $SETS->{control_charset}) eq 'Контроль'; 16 17 warn "Contenido Debug: Форма для редактирования пришла в кодировке ".$request->{local_codepage}."\n" if ($state->debug()); 18 19 my @properties = $object->structure(); 20 for (0..$#properties) 21 { 22 my $prop = $properties[$_]; 23 my $name = $prop->{attr}; 24 my $type = $prop->{type}; 25 26 next if ($name eq 'sections'); 27 next if ($name eq 'id'); 28 29 next if $prop->{hidden}; 30 next if $context =~ /(facil|post)/ && $prop->{$context.'show'}; 31 next if !$context && ($prop->{manshow} || $prop->{manager_hidden}); 32 33 if ( exists $SETS->{$name} ) { 34 if ($m->comp_exists("/contenido/components/outputs/$type.msn")) { 35 $object->{$name} = $m->comp("/contenido/components/outputs/$type.msn", SETS => $SETS, name => $name, object => $object ); 36 } else { 37 $object->{$name} = $m->comp('/contenido/components/filter.msn', str => $SETS->{$name} ); 38 } 39 } 40 41 } 42 43 # По идее - мы работаем с ссылкой, так что ничего не надо возвращать! 44 # O-ле! О-ле! О-ле! 45 return 1; 46 47 </%INIT> -
utf8/plugins/webshop/comps/contenido/webshop/delivery.html
1 %# vim:syn=mason 2 <& "/contenido/components/header.msn" &> 3 <& "/contenido/components/naviline.msn", sect_id => $owner->id &> 4 5 % if ($error) { 6 <div align="center" style="font-size:110%; color:red;"> 7 <% $error %> 8 </div> 9 <br><br> 10 % } 11 12 % if (!ref($document)) { 13 % if ($id) { 14 <div align="center" style="font-size:110%; color:red;"> 15 Документ с идентификатором <% $id %> не найден 16 </div> 17 <br><br> 18 % } elsif ($class) { 19 <!-- Блок с выбором нового документа для создания --> 20 <table width="50%" border="0"><tr><td> 21 <fieldset> 22 <legend>Выберите тип документа для создания</legend> 23 <& "/contenido/components/new_objects_form.msn", proto => 'documents', sect_id => $owner->id &> 24 </fieldset> 25 </td></tr></table> 26 % } else { 27 <div align="center" style="font-size:110%; color:red;"> 28 Неверный вызов документа!!! (отсутствуют id и class одновременно) 29 </div> 30 <br><br> 31 % } 32 33 % } else { 34 % if ( $document->postman_id == $user->id ) { 35 <& "/contenido/components/obj_list_js.msn", object => $document &> 36 <& "/contenido/webshop/components/order_form.msn", 37 context => 'post', 38 object => $document, 39 proto => 'documents', 40 sect_id => $owner->id, 41 clone => $clone, 42 filter_params => \%filter_params, 43 &> 44 % } else { 45 % my $profile = $keeper->get_user_by_id( $document->postman_id ); 46 <div style="padding:10px;"> 47 <b style="font-size:110%">Доставка ЗАКАЗА</b> 48 <p style="color:red"><b>Внимание!</b> Доставку заказа осуществляет <% $profile->name %></p> 49 <p><a href="./?ost=3"><< Вернуться в список доставки</a></p> 50 </div> 51 % } 52 % } 53 54 </body> 55 </html> 56 <%ARGS> 57 $p => 1 58 $class => 'webshop::Order' 59 $sect_id => undef 60 $s_alias => undef 61 $id => undef 62 $delete => undef 63 $save => undef 64 $clone => undef 65 $activate => undef 66 $deactivate => undef 67 </%ARGS> 68 <%INIT> 69 70 &abort404 unless $class; 71 my $error=''; 72 ### !!! При добавлении переменных в ARGS их надо внести в список исключений в структуре ниже 73 74 my $filter = $m->comp('/contenido/components/context.msn', name => 'filter'); 75 76 my $document; 77 my $new; 78 my $now = Contenido::DateTime->new; 79 80 if ($id && ($id !~ /\D/) && ($id > 0)) { 81 $document = $keeper->get_document_by_id($id, class=>$class); 82 if ( $clone && exists $document->{'attributes'}->{'dtime'} ) { 83 $document->dtime(undef); 84 } 85 } elsif ( ($class) && (length($class)>0) && (! ref($document)) ) { 86 $document = new $class ($keeper); 87 $new = 1; 88 my @properties = $document->structure(); 89 foreach my $prop ( @properties ) { 90 my $attr = $prop->{attr}; 91 ### !!! Если не стандартная переменная, то можем инициализировать 92 if ( exists $ARGS{$attr} && ! grep { $prop->{attr} eq $_ } qw( class sect_id id delete save clone s_alias activate deactivate p s use_section alpha alpha_search search_by search ) ) { 93 $document->$attr($ARGS{$attr}); 94 } 95 } 96 } 97 &abort404 unless ref $document; 98 99 my @props = $document->structure(); 100 my %filter_params; 101 if ($ARGS{use_section} && !grep { $_->{attr} eq 'use_section' } @props ) { 102 $filter_params{use_section} = $ARGS{use_section}; 103 $filter_params{class} = $document->class; 104 } 105 $filter_params{alpha} = $ARGS{alpha} if $ARGS{alpha} && !grep { $_->{attr} eq 'alpha' } @props; 106 $filter_params{alpha_search} = $ARGS{alpha_search} if $ARGS{alpha_search} && !grep { $_->{attr} eq 'alpha_search' } @props; 107 $filter_params{search_by} = $ARGS{search_by} if $ARGS{search_by} && !grep { $_->{attr} eq 'search_by' } @props; 108 $filter_params{search} = $ARGS{search} if $ARGS{search} && !grep { $_->{attr} eq 'search' } @props; 109 $filter_params{s} = $ARGS{s} if $ARGS{s} && !grep { $_->{attr} eq 's' } @props; 110 $filter_params{p} = $p if $p > 1; 111 my $return_params = join ('&', map { $_.'='.$filter_params{$_} } grep { $_ ne 's' } keys %filter_params ); 112 113 114 if ($s_alias) { 115 $sect_id = $project->s_alias->{$s_alias}; 116 } 117 118 if ( (! $sect_id) && (ref($document)) && ($document->id) ) { 119 $sect_id = $document->section(); 120 } 121 my $owner = $keeper->get_section_by_id ($sect_id || $Contenido::Section::ROOT || 1); 122 123 if (! ref($owner)) { 124 $owner = $keeper->get_section_by_id ($Contenido::Section::ROOT || 1); 125 } 126 if (! ref($owner)) { 127 warn "Contenido Die: Не могу найти корневую секцию\n"; 128 return undef; 129 } 130 131 if ( ref $document && !$document->postman_id ) { 132 $document->postman_id( $user->id ); 133 $document->store; 134 } 135 if (ref($document) && $document->id() && $document->section()) { 136 my $document_access = $user->section_accesses($user, $owner); 137 if ($document_access != 2) { 138 $m->clear_buffer; 139 $m->abort(403); 140 } 141 } 142 143 # Удаление... 144 if (defined($id) && ($id > 0) && $delete) { 145 $document->status( 5 ); 146 $document->store; 147 148 $m->redirect("./?ost=3".($return_params ? '&'.$return_params : '')); 149 } 150 151 # Сохранение существующего документа или создание нового... 152 # Кстати, пока никак не обрабатываются связи... 153 elsif ( $save == 1 ) 154 { 155 my $clonesource; 156 if ( $clone ) { 157 $clonesource = $keeper->get_document_by_id ($clone, 158 class => $document->class, 159 ); 160 } 161 if ($m->comp('/contenido/webshop/components/set_properties.msn', object => $document, SETS => \%ARGS, context => 'post') != 1) 162 { 163 # Ошибка, надо бы обработать... 164 warn "Contenido Warning: Не могу установить значения полей!\n"; 165 } 166 if ( $clone ) { 167 $m->comp('/contenido/components/clone_attachments.msn', object => $document, source => $clonesource ); 168 $document->sections( $clonesource->sections ); 169 } elsif ( $new ) { 170 $document->sections( $owner->id, $filter > 0 ? ($filter) : ()); 171 } 172 173 if ( $ARGS{_save_and_deliver} ) { 174 $document->status(4); 175 $document->postman_id( $user->id ); 176 $document->etime( $now->ymd('-').' '.$now->hms ); 177 } elsif ( $ARGS{_ret_manager} ) { 178 $document->status(1); 179 } elsif ( $ARGS{_ret_facility} ) { 180 $document->status(2); 181 } elsif ( $ARGS{_save_and_leave} ) { 182 } 183 184 unless ($document->store()) { 185 # Ошибка, надо бы обработать... 186 $error="Ошибка сохранения ($keeper->{last_error})"; 187 } else { 188 189 if ($ARGS{_save_and_deliver}) { 190 $m->redirect("./?ost=3"); 191 } elsif ($ARGS{_ret_manager}) { 192 $m->redirect("./?ost=3"); 193 } elsif ($ARGS{_ret_facility}) { 194 $m->redirect("./?ost=3"); 195 } elsif ($ARGS{_save_and_leave}) { 196 $m->redirect("./?ost=1".($return_params ? '&'.$return_params : '')); 197 } 198 199 $m->redirect("delivery.html?id=".$document->id.($return_params ? '&'.$return_params : '')); 200 } 201 } 202 203 </%INIT> -
utf8/plugins/webshop/comps/contenido/webshop/dhandler
1 <& $call, %ARGS &> 2 <%init> 3 4 my $call; 5 if ( $r->uri eq '/contenido/webshop/' ) { 6 $call = 'index.html'; 7 } else { 8 &abort404; 9 } 10 11 </%init> -
utf8/plugins/webshop/comps/contenido/webshop/facility.html
1 %# vim:syn=mason 2 <& "/contenido/components/header.msn" &> 3 <& "/contenido/components/naviline.msn", sect_id => $owner->id &> 4 5 % if ($error) { 6 <div align="center" style="font-size:110%; color:red;"> 7 <% $error %> 8 </div> 9 <br><br> 10 % } 11 12 % if (!ref($document)) { 13 % if ($id) { 14 <div align="center" style="font-size:110%; color:red;"> 15 Документ с идентификатором <% $id %> не найден 16 </div> 17 <br><br> 18 % } elsif ($class) { 19 <!-- Блок с выбором нового документа для создания --> 20 <table width="50%" border="0"><tr><td> 21 <fieldset> 22 <legend>Выберите тип документа для создания</legend> 23 <& "/contenido/components/new_objects_form.msn", proto => 'documents', sect_id => $owner->id &> 24 </fieldset> 25 </td></tr></table> 26 % } else { 27 <div align="center" style="font-size:110%; color:red;"> 28 Неверный вызов документа!!! (отсутствуют id и class одновременно) 29 </div> 30 <br><br> 31 % } 32 33 % } else { 34 35 % if ( $document->vault_id == $user->id ) { 36 <& "/contenido/components/obj_list_js.msn", object => $document &> 37 <& "/contenido/webshop/components/order_form.msn", 38 context => 'facil', 39 object => $document, 40 proto => 'documents', 41 sect_id => $owner->id, 42 clone => $clone, 43 filter_params => \%filter_params, 44 &> 45 % } else { 46 % my $profile = $keeper->get_user_by_id( $document->vault_id ); 47 <div style="padding:10px;"> 48 <b style="font-size:110%">Комплектация ЗАКАЗА</b> 49 <p style="color:red"><b>Внимание!</b> Комплектацией заказа занимается <% $profile->name %></p> 50 <p><a href="./?ost=2"><< Вернуться в список комплектации</a></p> 51 </div> 52 % } 53 % } 54 55 </body> 56 </html> 57 <%ARGS> 58 $p => 1 59 $class => 'webshop::Order' 60 $sect_id => undef 61 $s_alias => undef 62 $id => undef 63 $delete => undef 64 $save => undef 65 $clone => undef 66 $activate => undef 67 $deactivate => undef 68 </%ARGS> 69 <%INIT> 70 71 &abort404 unless $class; 72 my $error=''; 73 ### !!! При добавлении переменных в ARGS их надо внести в список исключений в структуре ниже 74 75 my $filter = $m->comp('/contenido/components/context.msn', name => 'filter'); 76 77 my $document; 78 my $new; 79 my $now = Contenido::DateTime->new; 80 81 if ($id && ($id !~ /\D/) && ($id > 0)) { 82 $document = $keeper->get_document_by_id($id, class=>$class); 83 if ( $clone && exists $document->{'attributes'}->{'dtime'} ) { 84 $document->dtime(undef); 85 } 86 } elsif ( ($class) && (length($class)>0) && (! ref($document)) ) { 87 $document = new $class ($keeper); 88 $new = 1; 89 my @properties = $document->structure(); 90 foreach my $prop ( @properties ) { 91 my $attr = $prop->{attr}; 92 ### !!! Если не стандартная переменная, то можем инициализировать 93 if ( exists $ARGS{$attr} && ! grep { $prop->{attr} eq $_ } qw( class sect_id id delete save clone s_alias activate deactivate p s use_section alpha alpha_search search_by search ) ) { 94 $document->$attr($ARGS{$attr}); 95 } 96 } 97 } 98 &abort404 unless ref $document; 99 100 my @props = $document->structure(); 101 my %filter_params; 102 if ($ARGS{use_section} && !grep { $_->{attr} eq 'use_section' } @props ) { 103 $filter_params{use_section} = $ARGS{use_section}; 104 $filter_params{class} = $document->class; 105 } 106 $filter_params{alpha} = $ARGS{alpha} if $ARGS{alpha} && !grep { $_->{attr} eq 'alpha' } @props; 107 $filter_params{alpha_search} = $ARGS{alpha_search} if $ARGS{alpha_search} && !grep { $_->{attr} eq 'alpha_search' } @props; 108 $filter_params{search_by} = $ARGS{search_by} if $ARGS{search_by} && !grep { $_->{attr} eq 'search_by' } @props; 109 $filter_params{search} = $ARGS{search} if $ARGS{search} && !grep { $_->{attr} eq 'search' } @props; 110 $filter_params{s} = $ARGS{s} if $ARGS{s} && !grep { $_->{attr} eq 's' } @props; 111 $filter_params{p} = $p if $p > 1; 112 my $return_params = join ('&', map { $_.'='.$filter_params{$_} } grep { $_ ne 's' } keys %filter_params ); 113 114 115 if ($s_alias) { 116 $sect_id = $project->s_alias->{$s_alias}; 117 } 118 119 if ( (! $sect_id) && (ref($document)) && ($document->id) ) { 120 $sect_id = $document->section(); 121 } 122 my $owner = $keeper->get_section_by_id ($sect_id || $Contenido::Section::ROOT || 1); 123 124 if (! ref($owner)) { 125 $owner = $keeper->get_section_by_id ($Contenido::Section::ROOT || 1); 126 } 127 if (! ref($owner)) { 128 warn "Contenido Die: Не могу найти корневую секцию\n"; 129 return undef; 130 } 131 132 if ( ref $document ) { 133 $document->vault_id( $user->id ); 134 $document->store; 135 } 136 if (ref($document) && $document->id() && $document->section()) { 137 my $document_access = $user->section_accesses($user, $owner); 138 if ($document_access != 2) { 139 $m->clear_buffer; 140 $m->abort(403); 141 } 142 } 143 144 # Удаление... 145 if (defined($id) && ($id > 0) && $delete) { 146 $document->status( 5 ); 147 $document->store; 148 149 $m->redirect("./?ost=2".($return_params ? '&'.$return_params : '')); 150 } 151 152 # Сохранение существующего документа или создание нового... 153 # Кстати, пока никак не обрабатываются связи... 154 elsif ( $save == 1 ) 155 { 156 if ($m->comp('/contenido/webshop/components/set_properties.msn', object => $document, SETS => \%ARGS, context => 'facil') != 1) 157 { 158 # Ошибка, надо бы обработать... 159 warn "Contenido Warning: Не могу установить значения полей!\n"; 160 } 161 162 if ( $ARGS{_save_and_deliver} ) { 163 $document->vault_id( $user->id ); 164 $document->ftime( $now->ymd('-').' '.$now->hms ); 165 $document->status(3); 166 } elsif ( $ARGS{_ret_manager} ) { 167 $document->status(1); 168 } elsif ( $ARGS{_save_and_leave} ) { 169 $document->vault_id( undef ); 170 $document->status(1); 171 } 172 173 unless ($document->store()) { 174 # Ошибка, надо бы обработать... 175 $error="Ошибка сохранения ($keeper->{last_error})"; 176 } else { 177 178 if ($ARGS{_save_and_deliver}) { 179 $m->redirect("./?ost=3"); 180 } elsif ($ARGS{_ret_manager}) { 181 $m->redirect("./?ost=2"); 182 } elsif ($ARGS{_save_and_leave}) { 183 $m->redirect("./?ost=2"); 184 } elsif ($ARGS{_save_and_leave}) { 185 $m->redirect("./?ost=1".($return_params ? '&'.$return_params : '')); 186 } 187 188 $m->redirect("take_care.html?id=".$document->id.($return_params ? '&'.$return_params : '')); 189 } 190 } 191 192 </%INIT> -
utf8/plugins/webshop/comps/contenido/webshop/index.html
1 <& "/contenido/components/header.msn" &> 2 3 <style> 4 <!-- 5 .inverted td { font-weight:bold; color:white; background-color:#8093B0; } 6 .inverted td a { color:white; font-weight:bold; } 7 //--> 8 </style> 9 10 <table width="100%" cellspacing="0" cellpadding="0" border="0"> 11 <tr valign="top"> 12 <td width="35%"> 13 14 <& /contenido/webshop/components/block_order_status_changer.msn, status => $ost &> 15 16 </td> 17 <td width="1%"> </td> 18 <td width="65%"> 19 20 <fieldset> 21 <legend>Заказы со статусом "<span style="color:yellow"><% $current_status->[1] %></span>"</legend> 22 23 % if ( $total ) { 24 25 <div style="font-size:75%; font-family:Arial;"> 26 <& /inc/pages_.msn, p=>$p, n=>$size, total=>$total, params=>\%filter_params, &> 27 <div style="height:5px"><spacer type="block" height="5"></div> 28 </div> 29 30 <& /contenido/webshop/components/order_browse.msn, documents => \@documents, columns => \@columns, filter => \%filter_params, status => $ost, %ARGS &> 31 32 <div style="font-size:75%; font-family:Arial;"> 33 <& /inc/pages_.msn, p=>$p, n=>$size, total=>$total, params=>\%filter_params, &> 34 <div style="height:5px"><spacer type="block" height="5"></div> 35 </div> 36 37 % } else { 38 <h4 align="center"><i>---- Нет документов -----</i></h4> 39 % } 40 41 42 </td> 43 <td width="1%"> </td> 44 </tr> 45 </table> 46 47 </body> 48 </html> 49 <%args> 50 51 $ost => 1 52 $p => 1 53 54 </%args> 55 <%init> 56 57 my %filter_params; 58 59 my (@documents, $total); 60 $filter_params{ost} = $ost if $ost != 1; 61 my $size = 40; 62 63 @documents = $keeper->get_documents( 64 class => 'webshop::Order', 65 status => $ost, 66 limit => $size, 67 offset => ($p-1)*$size, 68 ); 69 $total = $keeper->get_documents( 70 class => 'webshop::Order', 71 status => $ost, 72 count => 1, 73 ); 74 my @structure = webshop::Order->new( $keeper->{webshop} )->structure; 75 my @columns = sort { $a->{column} <=> $b->{column} } 76 grep { $_->{column} } @structure; 77 push @columns, {attr => '_act_', rusname => 'Действия'}; 78 my ($status_map) = grep { $_->{attr} eq 'status' } @structure; 79 my ($current_status) = grep { $_->[0] == $ost } @{$status_map->{cases}}; 80 81 </%init> -
utf8/plugins/webshop/comps/contenido/webshop/recount.html
1 <pre><% Dumper(\%ARGS) %></pre> 2 <%args> 3 4 $delete => [] 5 $update => undef 6 $id => undef 7 8 </%args> 9 <%init> 10 11 &abort404 unless $id && $id =~ /^\d+$/; 12 13 my $order = $keeper->{webshop}->get_orders( id => $id ); 14 &abort404 unless ref $order; 15 16 if ( $update ) { 17 my @delete = ref $delete ? @$delete : (); 18 my (%renumber, %reprice); 19 while ( my ($key, $value) = each %ARGS ) { 20 if ( $key =~ /item_(\d+)\.num/ ) { 21 my $id = $1; 22 $renumber{$id} = $value if $value =~ /^\d+$/; 23 } elsif ( $key =~ /item_(\d+)\.price/ ) { 24 my $id = $1; 25 $reprice{$id} = $value if $value =~ /^[\d\.]+$/; 26 } 27 } 28 my ($total, $sum, $new_basket) = $keeper->{webshop}->recount( 29 order_id=> $order->id, 30 delete => \@delete, 31 price => \%reprice, 32 session_no_store=>1, 33 renumber => \%renumber, 34 ); 35 $order->total( $total ); 36 $order->sum( $sum ); 37 $order->store; 38 $m->redirect('/contenido/webshop/take_care.html?id='.$id); 39 } 40 41 </%init> -
utf8/plugins/webshop/comps/contenido/webshop/subs/user_rights.msn
1 <%init> 2 3 if ( grep { $_->{attr} eq 'type' } $user->structure ) { 4 return $user->type; 5 } else { 6 return 0; 7 } 8 9 </%init> -
utf8/plugins/webshop/comps/contenido/webshop/take_care.html
1 %# vim:syn=mason 2 <& "/contenido/components/header.msn" &> 3 <& "/contenido/components/naviline.msn", sect_id => $owner->id &> 4 5 % if ($error) { 6 <div align="center" style="font-size:110%; color:red;"> 7 <% $error %> 8 </div> 9 <br><br> 10 % } 11 12 % if (!ref($document)) { 13 % if ($id) { 14 <div align="center" style="font-size:110%; color:red;"> 15 Документ с идентификатором <% $id %> не найден 16 </div> 17 <br><br> 18 % } elsif ($class) { 19 <!-- Блок с выбором нового документа для создания --> 20 <table width="50%" border="0"><tr><td> 21 <fieldset> 22 <legend>Выберите тип документа для создания</legend> 23 <& "/contenido/components/new_objects_form.msn", proto => 'documents', sect_id => $owner->id &> 24 </fieldset> 25 </td></tr></table> 26 % } else { 27 <div align="center" style="font-size:110%; color:red;"> 28 Неверный вызов документа!!! (отсутствуют id и class одновременно) 29 </div> 30 <br><br> 31 % } 32 33 % } else { 34 35 <& "/contenido/components/obj_list_js.msn", object => $document &> 36 <& "/contenido/webshop/components/order_form.msn", 37 object => $document, 38 proto => 'documents', 39 sect_id => $owner->id, 40 filter_params => \%filter_params, 41 &> 42 % } 43 44 </body> 45 </html> 46 <%ARGS> 47 $p => 1 48 $class => 'webshop::Order' 49 $sect_id => undef 50 $s_alias => undef 51 $id => undef 52 $delete => undef 53 $save => undef 54 </%ARGS> 55 <%INIT> 56 57 &abort404 unless $class; 58 my $error=''; 59 ### !!! При добавлении переменных в ARGS их надо внести в список исключений в структуре ниже 60 61 my $filter = $m->comp('/contenido/components/context.msn', name => 'filter'); 62 63 my $document; 64 my $new; 65 my $now = Contenido::DateTime->new; 66 67 if ($id && ($id !~ /\D/) && ($id > 0)) { 68 $document = $keeper->get_document_by_id($id, class=>$class); 69 } elsif ( ($class) && (length($class)>0) && (! ref($document)) ) { 70 $document = new $class ($keeper); 71 $new = 1; 72 my @properties = $document->structure(); 73 foreach my $prop ( @properties ) { 74 my $attr = $prop->{attr}; 75 ### !!! Если не стандартная переменная, то можем инициализировать 76 if ( exists $ARGS{$attr} && ! grep { $prop->{attr} eq $_ } qw( class sect_id id delete save s_alias p s use_section alpha alpha_search search_by search ) ) { 77 $document->$attr($ARGS{$attr}); 78 } 79 } 80 } 81 &abort404 unless ref $document; 82 83 my @props = $document->structure(); 84 my %filter_params; 85 if ($ARGS{use_section} && !grep { $_->{attr} eq 'use_section' } @props ) { 86 $filter_params{use_section} = $ARGS{use_section}; 87 $filter_params{class} = $document->class; 88 } 89 $filter_params{alpha} = $ARGS{alpha} if $ARGS{alpha} && !grep { $_->{attr} eq 'alpha' } @props; 90 $filter_params{alpha_search} = $ARGS{alpha_search} if $ARGS{alpha_search} && !grep { $_->{attr} eq 'alpha_search' } @props; 91 $filter_params{search_by} = $ARGS{search_by} if $ARGS{search_by} && !grep { $_->{attr} eq 'search_by' } @props; 92 $filter_params{search} = $ARGS{search} if $ARGS{search} && !grep { $_->{attr} eq 'search' } @props; 93 $filter_params{s} = $ARGS{s} if $ARGS{s} && !grep { $_->{attr} eq 's' } @props; 94 $filter_params{p} = $p if $p > 1; 95 my $return_params = join ('&', map { $_.'='.$filter_params{$_} } grep { $_ ne 's' } keys %filter_params ); 96 97 98 if ($s_alias) { 99 $sect_id = $project->s_alias->{$s_alias}; 100 } 101 102 if ( (! $sect_id) && (ref($document)) && ($document->id) ) { 103 $sect_id = $document->section(); 104 } 105 my $owner = $keeper->get_section_by_id ($sect_id || $Contenido::Section::ROOT || 1); 106 107 if (! ref($owner)) { 108 $owner = $keeper->get_section_by_id ($Contenido::Section::ROOT || 1); 109 } 110 if (! ref($owner)) { 111 warn "Contenido Die: Не могу найти корневую секцию\n"; 112 return undef; 113 } 114 115 if ( ref $document ) { 116 $document->manager_id( $user->id ); 117 $document->store; 118 } 119 if (ref($document) && $document->id() && $document->section()) { 120 my $document_access = $user->section_accesses($user, $owner); 121 if ($document_access != 2) { 122 $m->clear_buffer; 123 $m->abort(403); 124 } 125 } 126 127 # Удаление... 128 if (defined($id) && ($id > 0) && $delete) { 129 $document->status( 5 ); 130 $document->store; 131 132 $m->redirect("./?ost=1".($return_params ? '&'.$return_params : '')); 133 } 134 135 # Сохранение существующего документа или создание нового... 136 # Кстати, пока никак не обрабатываются связи... 137 elsif ( $save == 1 ) 138 { 139 if ($m->comp('/contenido/webshop/components/set_properties.msn', object => $document, SETS => \%ARGS) != 1) 140 { 141 # Ошибка, надо бы обработать... 142 warn "Contenido Warning: Не могу установить значения полей!\n"; 143 } 144 if ( $new ) { 145 $document->sections( $owner->id, $filter > 0 ? ($filter) : ()); 146 } 147 148 if ( $ARGS{_save_and_deliver} ) { 149 $document->manager_id( $user->id ); 150 $document->ftime( $now->ymd('-').' '.$now->hms ); 151 $document->status(3); 152 } elsif ( $ARGS{_save_and_complect} ) { 153 $document->manager_id( $user->id ); 154 $document->btime( $now->ymd('-').' '.$now->hms ); 155 $document->status(2); 156 } elsif ( $ARGS{_save_and_leave} ) { 157 $document->manager_id( undef ); 158 $document->status(1); 159 } 160 161 unless ($document->store()) { 162 # Ошибка, надо бы обработать... 163 $error="Ошибка сохранения ($keeper->{last_error})"; 164 } else { 165 166 if ($ARGS{_save_and_complect}) { 167 $m->redirect("./?ost=2"); 168 } elsif ($ARGS{_save_and_deliver}) { 169 $m->redirect("./?ost=3"); 170 } elsif ($ARGS{_save_and_leave}) { 171 $m->redirect("./?ost=1".($return_params ? '&'.$return_params : '')); 172 } 173 174 $m->redirect("take_care.html?id=".$document->id.($return_params ? '&'.$return_params : '')); 175 } 176 } 177 178 </%INIT> -
utf8/plugins/webshop/config.proto
1 ############################################################################# 2 # 3 # Параметры данного шаблона необходимо ВРУЧНУЮ добавить в config.mk проекта 4 # и привести в соответствие с требованиями проекта 5 # 6 ############################################################################# 7 8 PLUGINS += webshop 9 10 11 ############################################################################# 12 # Параметр испфльзуется для переопределения на уровне проекта таблицы или класса 13 # для хранения описания товара 14 15 ITEM_DOCUMENT_CLASS = webshop::Item 16 REWRITE += ITEM_DOCUMENT_CLASS 17 18 ITEM_DOCUMENT_TABLE = webshop::SQL::Items 19 REWRITE += ITEM_DOCUMENT_TABLE 20 -
utf8/plugins/webshop/lib/webshop/Address.pm
1 package webshop::Address; 2 3 use Contenido::Globals; 4 use base "Contenido::Document"; 5 sub extra_properties 6 { 7 return ( 8 { 'attr' => 'status', 'type' => 'status', 'rusname' => 'Статус заказа', 9 'cases' => [ 10 [0, 'Дополнительный адрес'], 11 [1, 'Основной адрес'], 12 ], 13 }, 14 { 'attr' => 'delivery', 'type' => 'lookup', 'rusname' => 'Тип доставки', 15 'lookup_opts' => { 16 'class' => 'webshop::Delivery', 17 }, 18 }, 19 { 'attr' => 'name', 'type' => 'string', 'rusname' => 'Контактное лицо' }, 20 { 'attr' => 'phone', 'type' => 'string', 'rusname' => 'Телефон для связи' }, 21 { 'attr' => 'zipcode', 'type' => 'string', 'rusname' => 'Почтовый индекс' }, 22 { 'attr' => 'town', 'type' => 'string', 'rusname' => 'Город' }, 23 { 'attr' => 'metro', 'type' => 'string', 'rusname' => 'Ближайшее метро' }, 24 { 'attr' => 'address', 'type' => 'text', 'rusname' => 'Адрес доставки', rows => 5 }, 25 { 'attr' => 'timeline', 'type' => 'string', 'rusname' => 'Предпочтительное время' }, 26 { 'attr' => 'description', 'type' => 'text', 'rusname' => 'Описание для курьера', rows => 5 }, 27 ) 28 } 29 30 sub class_name 31 { 32 return 'Заказ'; 33 } 34 35 sub class_description 36 { 37 return 'Заказ'; 38 } 39 40 sub class_table 41 { 42 return 'webshop::SQL::AddressTable'; 43 } 44 45 1; -
utf8/plugins/webshop/lib/webshop/Apache.pm
1 package webshop::Apache; 2 3 use strict; 4 use warnings 'all'; 5 6 use webshop::State; 7 use Contenido::Globals; 8 9 10 sub child_init { 11 # встраиваем keeper плагина в keeper проекта 12 $keeper->{webshop} = webshop::Keeper->new($state->webshop); 13 } 14 15 sub request_init { 16 } 17 18 sub child_exit { 19 } 20 21 1; -
utf8/plugins/webshop/lib/webshop/Basket.pm
1 package webshop::Basket; 2 3 use base "Contenido::Document"; 4 sub extra_properties 5 { 6 return ( 7 { 'attr' => 'status', 'type' => 'status', 'rusname' => 'Статус заказа', 8 'cases' => [ 9 [0, 'Элемент wish-листа'], 10 [1, 'Элемент корзины'], 11 ], 12 }, 13 { 'attr' => 'articul', 'type' => 'string', 'rusname' => 'Артикул' }, 14 { 'attr' => 'colour', 'type' => 'string', 'rusname' => 'Цвет' }, 15 { 'attr' => 'discount_flag', 'type' => 'string', 'rusname' => 'Наличие скидки' }, 16 { 'attr' => 'discount', 'type' => 'text', 'rusname' => 'Формула скидки', rows => 15 }, 17 ) 18 } 19 20 sub price_formatted { 21 my $self = shift; 22 23 my $price = $self->price; 24 $price = reverse $price; 25 $price =~ s/(\d{3})/$1\ /g; 26 $price = reverse $price; 27 28 return $price; 29 } 30 31 sub total_formatted { 32 my $self = shift; 33 34 my $price = $self->price * ($self->number || 0); 35 $price = reverse $price; 36 $price =~ s/(\d{3})/$1\ /g; 37 $price = reverse $price; 38 39 return $price; 40 } 41 42 sub class_name 43 { 44 return 'Позиция в корзине'; 45 } 46 47 sub class_description 48 { 49 return 'Позиция в корзине'; 50 } 51 52 sub class_table 53 { 54 return 'webshop::SQL::Basket'; 55 } 56 57 1; -
utf8/plugins/webshop/lib/webshop/Delivery.pm
1 package webshop::Delivery; 2 3 use base "Contenido::Document"; 4 sub extra_properties 5 { 6 return ( 7 { 'attr' => 'status', 'type' => 'status', 'rusname' => 'Статус', 8 'cases' => [ 9 [0, 'Не активна'], 10 [1, 'Действует'], 11 ], 12 }, 13 { 'attr' => 'dtime', 'hidden' => 1 }, 14 { 'attr' => 'price', 'type' => 'string', 'rusname' => 'Стоимость доставки (NN или NN%)', default => 0 }, 15 { 'attr' => 'abstr', 'type' => 'text', 'rusname' => 'Краткое описание' }, 16 { 'attr' => 'fields', 'type' => 'status_multi', 'rusname' => 'Поля, необходимые к заполнению', 17 'cases' => [ 18 ['timeline','Время заказа'], 19 ['zipcode','Почтовый индекс'], 20 ['town','Город'], 21 ['address','Адрес'], 22 ['metro','Ближайшее метро'], 23 ], 24 }, 25 ) 26 } 27 28 sub class_name 29 { 30 return 'Способ доставки'; 31 } 32 33 sub class_description 34 { 35 return 'Способ доставки'; 36 } 37 38 sub pre_store 39 { 40 my $self = shift; 41 42 my $default_section = $project->s_alias->{delivery} if ref $project->s_alias eq 'HASH'; 43 my $sections = $self->{sections}; 44 if ( $default_section ) { 45 if ( ref $sections eq 'ARRAY' && scalar @$sections ) { 46 my @new_sects = grep { $_ != $default_section } @$sections; 47 push @new_sects, $default_section; 48 $self->sections(@new_sects); 49 } elsif ( $sections && !ref $sections && $sections != $default_section ) { 50 my @new_sects = ($default_section, $sections); 51 $self->sections(@new_sects); 52 } else { 53 $self->sections($default_section); 54 } 55 } 56 57 return 1; 58 } 59 60 1; -
utf8/plugins/webshop/lib/webshop/DeliverySection.pm
1 package webshop::DeliverySection; 2 3 use Contenido::Section; 4 @ISA = ('Contenido::Section'); 5 6 sub extra_properties 7 { 8 return ( 9 { 'attr' => 'brief', 'type' => 'text', 'rusname' => 'Описание секции' }, 10 { 'attr' => 'default_document_class', 'default' => 'webshop::Delivery' }, 11 { 'attr' => '_sorted', 'default' => 1 }, 12 { 'attr' => 'filters', 'hidden' => 1 }, 13 { 'attr' => 'order_by', 'hidden' => 1 }, 14 ) 15 } 16 17 sub class_name 18 { 19 return 'Cпособы доставки'; 20 } 21 22 sub class_description 23 { 24 return 'Cпособы доставки'; 25 } 26 27 1; -
utf8/plugins/webshop/lib/webshop/Init.pm
1 package webshop::Init; 2 3 use strict; 4 use warnings 'all'; 5 6 use Contenido::Globals; 7 use webshop::Apache; 8 use webshop::Keeper; 9 10 11 # загрузка всех необходимых плагину классов 12 # webshop::SQL::SomeTable 13 # webshop::SomeClass 14 Contenido::Init::load_classes(qw( 15 webshop::SQL::Basket 16 webshop::SQL::Order 17 18 webshop::Address 19 webshop::Basket 20 webshop::Order 21 webshop::Delivery 22 23 webshop::DeliverySection 24 )); 25 26 sub init { 27 push @{ $state->{'available_documents'} }, ('webshop::Basket', 'webshop::Order', 'webshop::Delivery'); 28 push @{ $state->{'available_sections'} }, 'webshop::DeliverySection'; 29 0; 30 } 31 32 1; -
utf8/plugins/webshop/lib/webshop/Keeper.pm
1 package webshop::Keeper; 2 3 use strict; 4 use warnings 'all'; 5 use base qw(Contenido::Keeper); 6 7 use Data::Dumper; 8 use Contenido::Globals; 9 use webshop::Basket; 10 use webshop::SQL::Basket; 11 12 sub add_item { 13 my $self = shift; 14 my $object = shift; 15 my (%options) = @_; 16 17 return unless ref $object; 18 return unless $object->item_id && $object->number; 19 return unless $object->uid || $object->session; 20 21 22 my %opts; 23 if ( $object->uid ) { 24 $opts{uid} = $object->uid; 25 } elsif ( $object->session ) { 26 $opts{session} = $object->session; 27 } 28 my @items = $keeper->get_documents ( 29 class => 'webshop::Basket', 30 status => [0,1], 31 order_id=> 0, 32 %opts, 33 ); 34 my $total = 0; 35 my $sum = 0; 36 my $found = 0; 37 if ( @items ) { 38 foreach my $item ( @items ) { 39 if ( $object->item_id == $item->item_id && $object->color_id == $item->color_id ) { 40 $item->number($item->number + $object->number); 41 $item->status(1); 42 $item->store; 43 $found = 1; 44 } 45 $total += $item->number; 46 $sum += $item->number * $item->price; 47 } 48 } 49 unless ( $found ) { 50 $total += $object->number; 51 $sum += $object->number * $object->price; 52 $object->order_id(0); 53 $object->store; 54 } 55 my @plugins = split (/[\ |\t]+/, $state->{plugins}); 56 if ( grep { $_ eq 'session' } @plugins ) { 57 $keeper->{session}->store_value ( basket_total => $total, basket_sum => $sum ); 58 } 59 return ($total, $sum); 60 } 61 62 ### Метод приведения корзины для пользователя в момент логина 63 ############################################################# 64 sub merge_basket { 65 my $self = shift; 66 my (%opts) = @_; 67 68 warn "Merge begin: ".Dumper(\%opts)."\n" if $DEBUG; 69 return unless $opts{uid} && $opts{session}; 70 71 my @items = $keeper->get_documents ( 72 class => 'webshop::Basket', 73 status => [1,0], 74 order_id=> 0, 75 session => $opts{session}, 76 ); 77 foreach my $item ( @items ) { 78 $item->session(undef); 79 $item->uid( $opts{uid} ); 80 $item->store; 81 } 82 @items = $keeper->get_documents ( 83 class => 'webshop::Basket', 84 status => 1, 85 order_id=> 0, 86 uid => $opts{uid}, 87 ); 88 my $total = 0; 89 my $sum = 0; 90 foreach my $item ( @items ) { 91 $total += $item->number; 92 $sum += $item->number * $item->price; 93 } 94 my @plugins = split (/[\ |\t]+/, $state->{plugins}); 95 if ( grep { $_ eq 'session' } @plugins ) { 96 $keeper->{session}->store_value ( basket_total => $total, basket_sum => $sum ); 97 } 98 warn "Merge end\n" if $DEBUG; 99 return ($total, $sum); 100 } 101 102 103 sub get_basket { 104 my $self = shift; 105 my (%opts) = @_; 106 107 return unless $opts{uid} || $opts{session} || $opts{order_id}; 108 109 my $uid = delete $opts{uid}; 110 my $session = delete $opts{session}; 111 unless ( exists $opts{order_id} && $opts{order_id} ) { 112 $opts{order_id} = 0; 113 if ( $uid ) { 114 $opts{uid} = $uid; 115 } elsif ( $session ) { 116 $opts{session} = $session; 117 } 118 } 119 $opts{status} = 1 unless exists $opts{status} && defined $opts{status}; 120 my @items = $keeper->get_documents ( 121 class => 'webshop::Basket', 122 %opts, 123 ); 124 my $total = 0; 125 my $sum = 0; 126 foreach my $item ( @items ) { 127 if ( $item->status == 1 ) { 128 $total += $item->number; 129 $sum += $item->number * $item->price; 130 } 131 } 132 my @plugins = split (/[\ |\t]+/, $state->{plugins}); 133 if ( grep { $_ eq 'session' } @plugins ) { 134 $keeper->{session}->store_value ( basket_total => $total, basket_sum => $sum ); 135 } 136 return \@items; 137 } 138 139 140 sub clear_basket { 141 my $self = shift; 142 my (%opts) = @_; 143 144 return unless exists $opts{uid} || exists $opts{session}; 145 146 my $table_name = webshop::SQL::Basket->db_table; 147 my $request = "delete from $table_name where order_id = 0 AND status = 1 AND"; 148 my $dbh = $keeper->SQL; 149 my @vals; 150 if ( exists $opts{uid} && $opts{uid} ) { 151 $request .= " uid in (?)"; 152 push @vals, $opts{uid}; 153 } elsif ( exists $opts{session} ) { 154 $request .= " session in (?)"; 155 push @vals, $opts{session}; 156 } 157 warn "CLEAR: [$request]. VALS: [".join(',',@vals)."]\n" if $DEBUG; 158 my $statement = $dbh->prepare ($request); 159 $statement->execute( @vals ) || $log->error("DBI execute error on $request\n"."\ncalled with opts:\n".Data::Dumper::Dumper(\%opts));; 160 $statement->finish; 161 162 my @plugins = split (/[\ |\t]+/, $state->{plugins}); 163 if ( grep { $_ eq 'session' } @plugins ) { 164 $keeper->{session}->store_value ( basket_total => 0, basket_sum => 0 ); 165 } 166 } 167 168 169 sub clear_wishlist { 170 my $self = shift; 171 my (%opts) = @_; 172 173 return unless exists $opts{uid} || exists $opts{session}; 174 175 my $table_name = webshop::SQL::Basket->db_table; 176 my $request = "delete from $table_name where order_id = 0 AND status = 0 AND"; 177 my $dbh = $keeper->SQL; 178 my @vals; 179 if ( exists $opts{uid} ) { 180 $request .= " uid in (?)"; 181 push @vals, $opts{uid}; 182 } elsif ( exists $opts{session} ) { 183 $request .= " session in (?)"; 184 push @vals, $opts{session}; 185 } 186 my $statement = $dbh->prepare ($request); 187 $statement->execute( @vals ) || $log->error("DBI execute error on $request\n"."\ncalled with opts:\n".Data::Dumper::Dumper(\%opts));; 188 $statement->finish; 189 } 190 191 192 ### Метод пересчета корзины 193 # Принимает на вход параметры: 194 # session => session_id пользователя 195 # uid => UID пользователя 196 # delete => массив или отдельный item_id 197 # renumber => ссылка на хеш вида item => number 198 ############################################################# 199 sub recount { 200 my $self = shift; 201 my (%opts) = @_; 202 203 warn "Recount Started!!!\n" if $DEBUG; 204 return unless exists $opts{uid} || exists $opts{session} || exists $opts{order_id}; 205 my $basket = $self->get_basket ( %opts ); 206 return unless ref $basket eq 'ARRAY' && @$basket; 207 208 warn Dumper(\%opts) if $DEBUG; 209 210 my $total = 0; 211 my $sum = 0; 212 my @new_basket; 213 my $session_no_store = delete $opts{session_no_store}; 214 foreach my $item ( @$basket ) { 215 my $delete = 0; 216 if ( exists $opts{renumber} && ref $opts{renumber} eq 'HASH' && exists $opts{renumber}{$item->id} && int($opts{renumber}{$item->id}) == 0 ) { 217 $delete = 1; 218 } elsif ( exists $opts{delete} && ref $opts{delete} eq 'ARRAY' ) { 219 $delete = 1 if grep { $_ == $item->id } @{ $opts{delete} }; 220 } elsif ( exists $opts{delete} && $opts{delete} ) { 221 $delete = 1 if $item->id == $opts{delete}; 222 } 223 if ( $delete ) { 224 warn "Item ID=".$item->id." DELETE\n" if $DEBUG; 225 $item->delete(); 226 next; 227 } else { 228 my $store = 0; 229 if ( exists $opts{renumber} && ref $opts{renumber} eq 'HASH' && exists $opts{renumber}{$item->id} && $opts{renumber}{$item->id} != $item->number ) { 230 $item->number( $opts{renumber}{$item->id} ); 231 $store = 1; 232 } 233 if ( exists $opts{price} && ref $opts{price} eq 'HASH' && exists $opts{price}{$item->id} && $opts{price}{$item->id} != $item->price ) { 234 $item->price( $opts{price}{$item->id} ); 235 $store = 1; 236 } 237 $item->store if $store; 238 $total += $item->number; 239 $sum += $item->number * $item->price; 240 push @new_basket, $item; 241 } 242 } 243 my @plugins = split (/[\ |\t]+/, $state->{plugins}); 244 if ( !$session_no_store && grep { $_ eq 'session' } @plugins ) { 245 $keeper->{session}->store_value ( basket_total => $total, basket_sum => $sum ); 246 } 247 return ($total, $sum, \@new_basket); 248 } 249 250 251 sub get_orders { 252 my $self = shift; 253 my (%opts) = @_; 254 255 my $list = delete $opts{list}; 256 $opts{order_by} ||= 'status'; 257 my @items = $keeper->get_documents ( 258 class => 'webshop::Order', 259 %opts, 260 ); 261 if ( exists $opts{id} && defined $opts{id} && !ref $opts{id} ) { 262 if ( $list ) { 263 $items[0]->{list} = $self->get_order_list( order_id => $opts{id} ); 264 } 265 return $items[0]; 266 } else { 267 if ( $list ) { 268 map { $_->{list} = $self->get_order_list( order_id => $_->id ) } @items; 269 } 270 return \@items; 271 } 272 } 273 274 275 sub get_order_list { 276 my $self = shift; 277 my (%opts) = @_; 278 279 return unless $opts{order_id}; 280 281 $opts{status} = 1; 282 my @items = $keeper->get_documents ( 283 class => 'webshop::Basket', 284 %opts, 285 ); 286 my $total = 0; 287 my $sum = 0; 288 foreach my $item ( @items ) { 289 my $Item = $item->class->new( $keeper, $item->id ); 290 $item->{item} = $Item; 291 if ( $item->status == 1 ) { 292 $total += $item->number; 293 $sum += $item->number * $item->price; 294 } 295 } 296 return \@items; 297 } 298 299 sub price_format { 300 my $self = shift; 301 my $price = shift; 302 303 $price = reverse $price; 304 $price =~ s/(\d{3})/$1\ /g; 305 $price = reverse $price; 306 307 return $price; 308 } 309 310 311 1; -
utf8/plugins/webshop/lib/webshop/Order.pm
1 package webshop::Order; 2 3 use base "Contenido::Document"; 4 sub extra_properties 5 { 6 return ( 7 { 'attr' => 'status', 'type' => 'status', 'rusname' => 'Статус заказа', facilshow => 1, postshow => 1, 8 'cases' => [ 9 [0, 'открыт'], 10 [1, 'обрабатывается'], 11 [2, 'комплектуется'], 12 [3, 'в доставке'], 13 [4, 'доставлен'], 14 [5, 'отклонен'], 15 ], 16 }, 17 { 'attr' => 'delivery', 'type' => 'lookup', 'rusname' => 'Тип доставки', facilshow => 1, postshow => 1, 18 'lookup_opts' => { 19 'class' => 'webshop::Delivery', 20 }, 21 }, 22 { 'attr' => 'btime', 'type' => 'datetime', 'rusname' => 'Заказ отдан на комплектацию', 23 postshow => 1, facilshow => 1 }, 24 { 'attr' => 'ftime', 'type' => 'datetime', 'rusname' => 'Заказ передан в доставку', 25 manager_hidden => 1, postshow => 1, faciledit => 1 }, 26 { 'attr' => 'etime', 'type' => 'datetime', 'rusname' => 'Заказ доставлен', 27 manager_hidden => 1, postedit => 1, facilshow => 1 }, 28 { 'attr' => 'num', 'type' => 'integer', 'rusname' => 'Количество позиций', 29 manshow => 1, postshow => 1, facilshow => 1 }, 30 { 'attr' => 'sum', 'type' => 'string', 'rusname' => 'Сумма (total)', shortname => 'Сумма', 31 column => 5, postshow => 1, facilshow => 1 }, 32 { 'attr' => 'sum_delivery', 'type' => 'string', 'rusname' => 'Стоимость доставки', shortname => 'Доставка', 33 column => 6, postshow => 1, facilshow => 1 }, 34 { 'attr' => 'contact', 'type' => 'string', 'rusname' => 'Контактное лицо', facilshow => 1 }, 35 { 'attr' => 'email', 'type' => 'string', 'rusname' => 'E-mail для связи', shortname => 'E-mail', 36 column => 3, postshow => 1, facilshow => 1 }, 37 { 'attr' => 'phone', 'type' => 'string', 'rusname' => 'Телефон для связи', shortname => 'Тел.', 38 column => 4, postshow => 1, facilshow => 1 }, 39 { 'attr' => 'zipcode', 'type' => 'string', 'rusname' => 'Почтовый индекс', postshow => 1 }, 40 { 'attr' => 'town', 'type' => 'string', 'rusname' => 'Город', postshow => 1, facilshow => 1 }, 41 { 'attr' => 'metro', 'type' => 'string', 'rusname' => 'Ближайшее метро', postshow => 1 }, 42 { 'attr' => 'timeline', 'type' => 'string', 'rusname' => 'Предпочтительное время', postshow => 1 }, 43 { 'attr' => 'description', 'type' => 'text', 'rusname' => 'Описание для курьера', rows => 5, postshow => 1 }, 44 { 'attr' => 'facility_comment', 'type' => 'text', 'rusname' => 'Описание проблем с комплектацией', rows => 5, faciledit => 1 }, 45 { 'attr' => 'delivery_comment', 'type' => 'text', 'rusname' => 'Описание проблем с доставкой', rows => 5, postedit => 1 }, 46 { 'attr' => 'address', 'type' => 'text', 'rusname' => 'Адрес доставки', rows => 5, postedit => 1, facilshow => 1 }, 47 ) 48 } 49 50 sub sum_formatted { 51 my $self = shift; 52 53 my $price = $self->sum; 54 $price = reverse $price; 55 $price =~ s/(\d{3})/$1\ /g; 56 $price = reverse $price; 57 58 return $price; 59 } 60 61 sub total_formatted { 62 my $self = shift; 63 64 my $price = $self->sum + ($self->sum_delivery || 0); 65 $price = reverse $price; 66 $price =~ s/(\d{3})/$1\ /g; 67 $price = reverse $price; 68 69 return $price; 70 } 71 72 73 sub reject { 74 my $self = shift; 75 76 my $query = $self->{keeper}->SQL->prepare("delete from basket where order_id = ? and uid = ?"); 77 $query->execute( $self->id, $self->uid ); 78 $self->delete; 79 } 80 81 82 sub class_name 83 { 84 return 'Заказ'; 85 } 86 87 sub class_description 88 { 89 return 'Заказ'; 90 } 91 92 sub class_table 93 { 94 return 'webshop::SQL::Order'; 95 } 96 97 98 sub post_delete 99 { 100 my $self = shift; 101 my @items = $self->keeper->get_documents( 102 class => 'webshop::Basket', 103 order_id => $self->id, 104 ); 105 foreach my $item ( @items ) { 106 $item->delete( attachments => 1 ); 107 } 108 1; 109 } 110 111 1; -
utf8/plugins/webshop/lib/webshop/SQL/AddressTable.pm
1 package webshop::SQL::AddressTable; 2 3 use base 'SQL::DocumentTable'; 4 5 sub db_table 6 { 7 return 'adresses'; 8 } 9 10 my $available_filters = [qw( 11 12 _class_filter 13 _status_filter 14 _in_id_filter 15 _id_filter 16 _name_filter 17 _class_excludes_filter 18 _sfilter_filter 19 _excludes_filter 20 _datetime_filter 21 _date_equal_filter 22 _date_filter 23 _previous_days_filter 24 _s_filter 25 26 _uid_filter 27 )]; 28 29 sub available_filters { 30 return $available_filters; 31 } 32 33 34 # ---------------------------------------------------------------------------- 35 # Свойства храним в массивах, потому что порядок важен! 36 # Это общие свойства - одинаковые для всех документов. 37 # 38 # attr - обязательный параметр, название атрибута; 39 # type - тип аттрибута, требуется для отображдения; 40 # rusname - русское название, опять же требуется для отображения; 41 # hidden - равен 1, когда 42 # readonly - инициализации при записи только без изменения в дальнейшем 43 # db_field - поле в таблице 44 # default - значение по умолчанию (поле всегда имеет это значение) 45 # ---------------------------------------------------------------------------- 46 sub required_properties 47 { 48 my $self = shift; 49 50 my @parent_properties = $self->SUPER::required_properties; 51 return ( 52 @parent_properties, 53 { # User ID 54 'attr' => 'uid', 55 'type' => 'string', 56 'rusname' => 'ID пользователя', 57 # 'hidden' => 1, 58 'db_field' => 'uid', 59 'db_type' => 'integer', 60 'db_opts' => "not null default 0", 61 'default' => 0, 62 }, 63 ); 64 } 65 66 ########### FILTERS DESCRIPTION ############################################################################### 67 sub _uid_filter { 68 my ($self,%opts)=@_; 69 return undef unless ( exists $opts{uid} ); 70 return &SQL::Common::_generic_int_filter('d.uid', $opts{uid}); 71 } 72 73 1; -
utf8/plugins/webshop/lib/webshop/SQL/Basket.pm
1 package webshop::SQL::Basket; 2 3 use base 'SQL::DocumentTable'; 4 5 sub db_table 6 { 7 return 'basket'; 8 } 9 10 11 sub available_filters { 12 my @available_filters = qw( 13 14 _class_filter 15 _status_filter 16 _in_id_filter 17 _id_filter 18 _name_filter 19 _class_excludes_filter 20 _sfilter_filter 21 _excludes_filter 22 _datetime_filter 23 _date_equal_filter 24 _date_filter 25 _previous_days_filter 26 _s_filter 27 28 _color_filter 29 _session_filter 30 _uid_filter 31 _order_id_filter 32 _item_filter 33 ); 34 35 return \@available_filters; 36 } 37 38 # ---------------------------------------------------------------------------- 39 # Свойства храним в массивах, потому что порядок важен! 40 # Это общие свойства - одинаковые для всех документов. 41 # 42 # attr - обязательный параметр, название атрибута; 43 # type - тип аттрибута, требуется для отображдения; 44 # rusname - русское название, опять же требуется для отображения; 45 # hidden - равен 1, когда 46 # readonly - инициализации при записи только без изменения в дальнейшем 47 # db_field - поле в таблице 48 # default - значение по умолчанию (поле всегда имеет это значение) 49 # ---------------------------------------------------------------------------- 50 sub required_properties 51 { 52 my $self = shift; 53 54 my @parent_properties = $self->SUPER::required_properties; 55 return ( 56 @parent_properties, 57 { 58 'attr' => 'uid', 59 'type' => 'integer', 60 'rusname' => 'Идентификатор пользователя', 61 'lookup_opts' => { 62 'class' => $self->profile_class(), 63 'search_by' => 'login', 64 }, 65 'db_field' => 'uid', 66 'db_type' => 'integer', 67 'db_opts' => "default 0", 68 }, 69 { # ID товара 70 'attr' => 'item_id', 71 'type' => 'integer', 72 'rusname' => 'ID товара', 73 'hidden' => 1, 74 'db_field' => 'item_id', 75 'db_type' => 'integer', 76 'db_opts' => "not null", 77 }, 78 { 79 'attr' => 'item_class', 80 'type' => 'string', 81 'rusname' => 'Класс товарной позиции', 82 'hidden' => 1, 83 'db_field' => 'item_class', 84 'db_type' => 'text', 85 }, 86 { 87 'attr' => 'item_table', 88 'type' => 'string', 89 'rusname' => 'Класс таблицы товарной позиции', 90 'hidden' => 1, 91 'db_field' => 'item_table', 92 'db_type' => 'text', 93 }, 94 { 95 'attr' => 'number', 96 'type' => 'integer', 97 'rusname' => 'Количество позиций', 98 'db_field' => 'number', 99 'db_type' => 'integer', 100 'db_opts' => "default 0", 101 }, 102 { 103 'attr' => 'price', 104 'type' => 'string', 105 'rusname' => 'Цена позиции', 106 'db_field' => 'price', 107 'db_type' => 'float', 108 'db_opts' => "default 0", 109 }, 110 { # ID заказа 111 'attr' => 'order_id', 112 'type' => 'integer', 113 'rusname' => 'ID заказа', 114 'hidden' => 1, 115 'db_field' => 'order_id', 116 'db_type' => 'integer', 117 'db_opts' => "default 0", 118 }, 119 { # ID цвета 120 'attr' => 'color_id', 121 'type' => 'integer', 122 'rusname' => 'ID цвета', 123 'hidden' => 1, 124 'db_field' => 'color_id', 125 'db_type' => 'integer', 126 }, 127 { # ID Сессии 128 'attr' => 'session', 129 'type' => 'string', 130 'rusname' => 'ID Сессии пользователя', 131 'db_field' => 'session', 132 'db_type' => 'text', 133 }, 134 ); 135 } 136 137 138 sub profile_class () { 139 my $self = shift; 140 return ref $self->{keeper} ? $self->{keeper}{webshop}{state}->profile_document_class : undef; 141 } 142 143 144 ########### FILTERS DESCRIPTION ############################################################################### 145 sub _uid_filter { 146 my ($self,%opts)=@_; 147 return undef unless ( exists $opts{uid} ); 148 return &SQL::Common::_generic_int_filter('d.uid', $opts{uid}); 149 } 150 151 sub _session_filter { 152 my ($self,%opts)=@_; 153 return undef unless ( exists $opts{session} ); 154 return &SQL::Common::_generic_text_filter('d.session', $opts{session}); 155 } 156 157 sub _item_filter { 158 my ($self,%opts)=@_; 159 return undef unless ( exists $opts{item} ); 160 return &SQL::Common::_generic_int_filter('d.item_id', $opts{item}); 161 } 162 163 sub _color_filter { 164 my ($self,%opts)=@_; 165 return undef unless ( exists $opts{color} ); 166 return &SQL::Common::_generic_int_filter('d.color_id', $opts{color}); 167 } 168 169 sub _order_id_filter { 170 my ($self,%opts)=@_; 171 return undef unless ( exists $opts{order_id} ); 172 return &SQL::Common::_generic_int_filter('d.order_id', $opts{order_id}); 173 } 174 175 176 1; -
utf8/plugins/webshop/lib/webshop/SQL/Order.pm
1 package webshop::SQL::Order; 2 3 use base 'SQL::DocumentTable'; 4 5 sub db_table 6 { 7 return 'orders'; 8 } 9 10 my $available_filters = [qw( 11 12 _class_filter 13 _status_filter 14 _in_id_filter 15 _id_filter 16 _name_filter 17 _class_excludes_filter 18 _sfilter_filter 19 _excludes_filter 20 _datetime_filter 21 _date_equal_filter 22 _date_filter 23 _previous_days_filter 24 _s_filter 25 26 _uid_filter 27 )]; 28 29 sub available_filters { 30 return $available_filters; 31 } 32 33 my @required_properties = ( 34 { # Идентификатор документа, сквозной по всем типам... 35 'attr' => 'id', 36 'type' => 'integer', 37 'rusname' => 'Идентификатор документа', 38 'hidden' => 1, 39 'readonly' => 1, 40 'auto' => 1, 41 'db_field' => 'id', 42 'db_type' => 'integer', 43 'db_opts' => "not null default nextval('public.documents_id_seq'::text)", 44 }, 45 { # Класс документа... 46 'attr' => 'class', 47 'type' => 'string', 48 'rusname' => 'Класс документа', 49 'hidden' => 1, 50 'readonly' => 1, 51 'db_field' => 'class', 52 'db_type' => 'varchar(48)', 53 'db_opts' => 'not null', 54 }, 55 { # Название (не используется) 56 'attr' => 'name', 57 'type' => 'string', 58 'rusname' => 'Имя заказчика', 59 'column' => 2, 60 'db_field' => 'name', 61 'db_type' => 'varchar(255)', 62 }, 63 { # User ID 64 'attr' => 'uid', 65 'type' => 'string', 66 'rusname' => 'ID пользователя', 67 # 'hidden' => 1, 68 'db_field' => 'uid', 69 'db_type' => 'integer', 70 'db_opts' => "not null default 0", 71 'default' => 0, 72 }, 73 { # User ID 74 'attr' => 'manager_id', 75 'type' => 'string', 76 'rusname' => 'ID менеджера', 77 'hidden' => 1, 78 'db_field' => 'manager_id', 79 'db_type' => 'integer', 80 'db_opts' => "not null default 0", 81 'default' => 0, 82 }, 83 { # User ID 84 'attr' => 'vault_id', 85 'type' => 'string', 86 'rusname' => 'ID специалиста комплектации', 87 'hidden' => 1, 88 'db_field' => 'vault_id', 89 'db_type' => 'integer', 90 'db_opts' => "not null default 0", 91 'default' => 0, 92 }, 93 { # User ID 94 'attr' => 'postman_id', 95 'type' => 'string', 96 'rusname' => 'ID курьера', 97 'hidden' => 1, 98 'db_field' => 'postman_id', 99 'db_type' => 'integer', 100 'db_opts' => "not null default 0", 101 'default' => 0, 102 }, 103 { # Время создания документа, служебное поле... 104 'attr' => 'ctime', 105 'type' => 'datetime', 106 'rusname' => 'Время создания', 107 'readonly' => 1, 108 'auto' => 1, 109 'hidden' => 1, 110 'db_field' => 'ctime', 111 'db_type' => 'timestamp', 112 'db_opts' => 'not null default now()', 113 'default' => 'CURRENT_TIMESTAMP', 114 }, 115 { # Время модификации документа, служебное поле... 116 'attr' => 'mtime', 117 'type' => 'datetime', 118 'rusname' => 'Время модификации', 119 'hidden' => 1, 120 'auto' => 1, 121 'db_field' => 'mtime', 122 'db_type' => 'timestamp', 123 'db_opts' => 'not null default now()', 124 'default' => 'CURRENT_TIMESTAMP', 125 }, 126 { # Дата и время документа... 127 'attr' => 'dtime', 128 'type' => 'datetime', 129 'rusname' => 'Заказ подтвержден', 130 'column' => 1, 131 'postshow' => 1, 132 'facilshow' => 1, 133 'db_field' => 'dtime', 134 'db_type' => 'timestamp', 135 'db_opts' => 'not null default now()', 136 'default' => 'CURRENT_TIMESTAMP', 137 }, 138 { # Массив секций, обрабатывается специальным образом... 139 'attr' => 'sections', 140 'type' => 'sections_list', 141 'rusname' => 'Секции', 142 'hidden' => 1, 143 'db_field' => 'sections', 144 'db_type' => 'integer[]', 145 }, 146 { # Одно поле статуса является встроенным... 147 'attr' => 'status', 148 'type' => 'status', 149 'postshow' => 1, 150 'facilshow' => 1, 151 'column' => 7, 152 'rusname' => 'Статус', 153 'db_field' => 'status', 154 'db_type' => 'integer', 155 }, 156 ); 157 158 # ---------------------------------------------------------------------------- 159 # Свойства храним в массивах, потому что порядок важен! 160 # Это общие свойства - одинаковые для всех документов. 161 # 162 # attr - обязательный параметр, название атрибута; 163 # type - тип аттрибута, требуется для отображдения; 164 # rusname - русское название, опять же требуется для отображения; 165 # hidden - равен 1, когда 166 # readonly - инициализации при записи только без изменения в дальнейшем 167 # db_field - поле в таблице 168 # default - значение по умолчанию (поле всегда имеет это значение) 169 # ---------------------------------------------------------------------------- 170 sub required_properties 171 { 172 return @required_properties; 173 } 174 175 ########### FILTERS DESCRIPTION ############################################################################### 176 sub _uid_filter { 177 my ($self,%opts)=@_; 178 return undef unless ( exists $opts{uid} ); 179 return &SQL::Common::_generic_int_filter('d.uid', $opts{uid}); 180 } 181 182 1; -
utf8/plugins/webshop/lib/webshop/State.pm.proto
1 package webshop::State; 2 3 use strict; 4 use warnings 'all'; 5 use vars qw($AUTOLOAD); 6 7 8 sub new { 9 my ($proto) = @_; 10 my $class = ref($proto) || $proto; 11 my $self = {}; 12 bless $self, $class; 13 14 # зашитая конфигурация плагина 15 $self->{db_type} = 'none'; 16 $self->{db_keepalive} = 0; 17 # $self->{db_host} = ''; 18 # $self->{db_name} = ''; 19 # $self->{db_user} = ''; 20 # $self->{db_password} = ''; 21 # $self->{db_port} = ''; 22 $self->{profile_document_class} = '@PROFILE_DOCUMENT_CLASS@' || 'users::UserProfile'; 23 $self->{item_document_class} = '@ITEM_DOCUMENT_CLASS@' || 'webshop::Item'; 24 25 $self->_init_(); 26 $self; 27 } 28 29 sub info { 30 my $self = shift; 31 return unless ref $self; 32 33 for (sort keys %{$self->{attributes}}) { 34 my $la = length $_; 35 warn "\t$_".("\t" x (2-int($la/8))).": $self->{$_}\n"; 36 } 37 } 38 39 sub _init_ { 40 my $self = shift; 41 42 # зашитая конфигурация плагина 43 $self->{attributes}->{$_} = 'SCALAR' for qw( 44 profile_document_class 45 item_document_class 46 db_type 47 db_keepalive 48 ); 49 # db_keepalive 50 # db_host 51 # db_port 52 # db_name 53 # db_user 54 # db_password 55 } 56 57 sub AUTOLOAD { 58 my $self = shift; 59 my $attribute = $AUTOLOAD; 60 61 $attribute =~ s/.*:://; 62 return unless $attribute =~ /[^A-Z]/; # Отключаем методы типа DESTROY 63 64 if (!exists $self->{attributes}->{$attribute}) { 65 warn "Contenido Error (webshop::State): Вызов метода, для которого не существует обрабатываемого свойства: ->$attribute()\n"; 66 return; 67 } 68 69 $self->{$attribute} = shift @_ if $#_>=0; 70 $self->{$attribute}; 71 } 72 73 1; -
utf8/plugins/webshop/sql/TOAST/adresses.sql
1 CREATE TABLE adresses ( 2 id integer DEFAULT nextval(('public.documents_id_seq'::text)::regclass) NOT NULL, 3 ctime timestamp without time zone DEFAULT now() NOT NULL, 4 mtime timestamp without time zone DEFAULT now() NOT NULL, 5 dtime timestamp without time zone DEFAULT now() NOT NULL, 6 class text DEFAULT 'webshop::Address'::text NOT NULL, 7 status smallint default 0 NOT NULL, 8 sections integer, 9 uid integer not null, 10 name text, 11 data text 12 ); 13 14 CREATE INDEX adresses_sections ON adresses USING btree (sections); 15 CREATE INDEX adresses_uid ON adresses USING btree (uid); -
utf8/plugins/webshop/sql/TOAST/basket.sql
1 CREATE TABLE basket ( 2 id integer DEFAULT nextval(('public.documents_id_seq'::text)::regclass) NOT NULL, 3 ctime timestamp without time zone DEFAULT now() NOT NULL, 4 mtime timestamp without time zone DEFAULT now() NOT NULL, 5 dtime timestamp without time zone DEFAULT now() NOT NULL, 6 class text DEFAULT 'webshop::Basket'::text NOT NULL, 7 status smallint default 0 NOT NULL, 8 sections integer[], 9 uid integer, 10 item_id integer not null, 11 item_class text, 12 item_table text, 13 order_id integer, 14 color_id integer, 15 session text, 16 number integer default 0, 17 price float default 0, 18 name text, 19 data text 20 ); 21 22 CREATE INDEX basket_order_id ON basket USING btree (order_id); 23 CREATE INDEX basket_sections ON basket USING gist (sections); 24 CREATE INDEX basket_session ON basket USING btree (session) where session is not null; 25 CREATE INDEX basket_uid ON basket USING btree (uid); -
utf8/plugins/webshop/sql/TOAST/orders.sql
1 CREATE TABLE orders ( 2 id integer DEFAULT nextval(('public.documents_id_seq'::text)::regclass) NOT NULL, 3 ctime timestamp without time zone DEFAULT now() NOT NULL, 4 mtime timestamp without time zone DEFAULT now() NOT NULL, 5 dtime timestamp without time zone DEFAULT now() NOT NULL, 6 class text DEFAULT 'webshop::Order'::text NOT NULL, 7 status smallint default 0 NOT NULL, 8 sections integer[], 9 uid integer, 10 manager_id integer, 11 vault_id integer, 12 postman_id integer, 13 session text, 14 name text, 15 data text 16 ); 17 18 CREATE INDEX orders_sections ON orders USING gist (sections); 19 CREATE INDEX orders_session ON orders USING btree (session) where session is not null; 20 CREATE INDEX orders_uid ON orders USING btree (uid) where uid is not null;