30 require
'../main.inc.php';
31 require_once DOL_DOCUMENT_ROOT.
'/delivery/class/delivery.class.php';
32 require_once DOL_DOCUMENT_ROOT.
'/core/modules/delivery/modules_delivery.php';
33 require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formfile.class.php';
34 require_once DOL_DOCUMENT_ROOT.
'/core/lib/sendings.lib.php';
35 require_once DOL_DOCUMENT_ROOT.
'/core/class/doleditor.class.php';
36 require_once DOL_DOCUMENT_ROOT.
'/core/class/extrafields.class.php';
37 if (!empty($conf->product->enabled) || !empty($conf->service->enabled))
38 require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
39 if (!empty($conf->expedition_bon->enabled))
40 require_once DOL_DOCUMENT_ROOT.
'/expedition/class/expedition.class.php';
41 if (!empty($conf->stock->enabled))
42 require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/entrepot.class.php';
43 if (!empty($conf->projet->enabled)) {
44 require_once DOL_DOCUMENT_ROOT.
'/projet/class/project.class.php';
45 require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formprojet.class.php';
49 $langs->loadLangs(array(
"sendings",
"bills",
'deliveries',
'orders'));
51 if (!empty($conf->incoterm->enabled)) $langs->load(
'incoterm');
53 $action =
GETPOST(
'action',
'aZ09');
54 $confirm =
GETPOST(
'confirm',
'alpha');
55 $backtopage =
GETPOST(
'backtopage',
'alpha');
59 if ($user->socid) $socid = $user->socid;
60 $result =
restrictedArea($user,
'expedition', $id,
'delivery',
'delivery');
66 $extrafields->fetch_name_optionals_label($object->table_element);
69 $extrafields->fetch_name_optionals_label($object->table_element_line);
72 include DOL_DOCUMENT_ROOT.
'/core/actions_fetchobject.inc.php';
75 $hookmanager->initHooks(array(
'deliverycard',
'globalcard'));
84 $parameters = array();
85 $reshook = $hookmanager->executeHooks(
'doActions', $parameters, $object, $action);
91 $object->date_delivery =
dol_now();
92 $object->note =
GETPOST(
"note",
'restricthtml');
93 $object->note_private =
GETPOST(
"note",
'restricthtml');
94 $object->commande_id =
GETPOST(
"commande_id",
'int');
95 $object->fk_incoterms =
GETPOST(
'incoterm_id',
'int');
97 if (!$conf->expedition_bon->enabled && !empty($conf->stock->enabled)) {
98 $expedition->entrepot_id =
GETPOST(
'entrepot_id');
103 $commande->fetch($object->commande_id);
104 $commande->fetch_lines();
105 $num = count($commande->lines);
106 for ($i = 0; $i < $num; $i++)
117 $ret = $object->create($user);
120 header(
"Location: ".
$_SERVER[
'PHP_SELF'].
"?id=".$object->id);
128 } elseif ($action ==
'confirm_valid' && $confirm ==
'yes' &&
129 ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->expedition->delivery->creer))
130 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->expedition->delivery_advance->validate)))
133 $result = $object->valid($user);
136 if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
138 $outputlangs = $langs;
140 if ($conf->global->MAIN_MULTILANGS && empty($newlang) &&
GETPOST(
'lang_id',
'aZ09')) $newlang =
GETPOST(
'lang_id',
'aZ09');
141 if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang;
142 if (!empty($newlang)) {
144 $outputlangs->setDefaultLang($newlang);
146 $model = $object->model_pdf;
147 $ret = $object->fetch($id);
149 $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
154 if ($action ==
'confirm_delete' && $confirm ==
'yes' && $user->rights->expedition->delivery->supprimer)
157 $result = $object->delete();
162 if (!empty($backtopage)) header(
"Location: ".$backtopage);
163 else header(
"Location: ".DOL_URL_ROOT.
'/expedition/list.php?restore_lastsearch_values=1');
170 if ($action ==
'setdate_delivery' && $user->rights->expedition->delivery->creer)
172 $datedelivery =
dol_mktime(
GETPOST(
'liv_hour',
'int'),
GETPOST(
'liv_min',
'int'), 0,
GETPOST(
'liv_month',
'int'),
GETPOST(
'liv_day',
'int'),
GETPOST(
'liv_year',
'int'));
173 $result = $object->setDeliveryDate($user, $datedelivery);
176 $mesg =
'<div class="error">'.$object->error.
'</div>';
181 elseif ($action ==
'set_incoterms' && !empty($conf->incoterm->enabled))
183 $result = $object->setIncoterms((
int)
GETPOST(
'incoterm_id',
'int'),
GETPOST(
'location_incoterms',
'alpha'));
187 if ($action ==
'update_extras')
192 $ret = $extrafields->setOptionalsFromPost(null, $object,
GETPOST(
'attribute',
'restricthtml'));
193 if ($ret < 0) $error++;
198 $result = $object->insertExtraFields(
'DELIVERY_MODIFY');
207 $action =
'edit_extras';
211 if ($action ==
'update_extras_line')
213 $array_options = array();
214 $num = count($object->lines);
216 for ($i = 0; $i < $num; $i++)
219 $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
220 $array_options[$i] = $extrafields->getOptionalsFromPost($extralabelsline, $i);
222 if (is_array($extralabelsline)) {
224 foreach ($extralabelsline as $key => $value) {
225 unset($_POST[
"options_".$key]);
229 $ret = $object->update_line($object->lines[$i]->id, $array_options[$i]);
232 $mesg =
'<div class="error">'.$object->error.
'</div>';
240 $upload_dir = $conf->expedition->dir_output.
'/receipt';
241 $permissiontoadd = $user->rights->expedition->creer;
242 include DOL_DOCUMENT_ROOT.
'/core/actions_builddoc.inc.php';
244 include DOL_DOCUMENT_ROOT.
'/core/actions_printing.inc.php';
251 llxHeader(
'', $langs->trans(
'Delivery'),
'Livraison');
253 $form =
new Form($db);
256 if ($action ==
'create')
265 $result = $expedition->fetch($object->origin_id);
266 $typeobject = $expedition->origin;
267 if ($object->origin_id > 0)
269 $object->fetch_origin();
275 $soc->fetch($object->socid);
279 print '<form action="'.$_SERVER[
"PHP_SELF"].
'" method="post">';
280 print '<input type="hidden" name="token" value="'.newToken().
'">';
281 print '<input type="hidden" name="action" value="update_extras_line">';
282 print '<input type="hidden" name="origin" value="'.$origin.
'">';
283 print '<input type="hidden" name="id" value="'.$object->id.
'">';
284 print '<input type="hidden" name="ref" value="'.$object->ref.
'">';
292 if ($action ==
'delete')
294 $expedition_id =
GETPOST(
"expid");
295 print $form->formconfirm(
$_SERVER[
'PHP_SELF'].
'?id='.$object->id.
'&expid='.$expedition_id.
'&backtopage='.urlencode($backtopage), $langs->trans(
"DeleteDeliveryReceipt"), $langs->trans(
"DeleteDeliveryReceiptConfirm", $object->ref),
'confirm_delete',
'',
'', 1);
301 if ($action ==
'valid')
303 print $form->formconfirm(
$_SERVER[
'PHP_SELF'].
'?id='.$object->id, $langs->trans(
"ValidateDeliveryReceipt"), $langs->trans(
"ValidateDeliveryReceiptConfirm", $object->ref),
'confirm_valid',
'',
'', 1);
311 if ($typeobject ==
'commande' && $expedition->origin_id > 0 && !empty($conf->commande->enabled))
314 $objectsrc->fetch($expedition->origin_id);
316 if ($typeobject ==
'propal' && $expedition->origin_id > 0 && !empty($conf->propal->enabled))
318 $objectsrc =
new Propal($db);
319 $objectsrc->fetch($expedition->origin_id);
323 $linkback =
'<a href="'.DOL_URL_ROOT.
'/expedition/list.php?restore_lastsearch_values=1'.(!empty($socid) ?
'&socid='.$socid :
'').
'">'.$langs->trans(
"BackToList").
'</a>';
325 $morehtmlref =
'<div class="refidno">';
327 $morehtmlref .= $form->editfieldkey(
"RefCustomer",
'', $expedition->ref_customer, $expedition, $user->rights->expedition->creer,
'string',
'', 0, 1);
328 $morehtmlref .= $form->editfieldval(
"RefCustomer",
'', $expedition->ref_customer, $expedition, $user->rights->expedition->creer,
'string',
'', null, null,
'', 1);
329 $morehtmlref .=
'<br>'.$langs->trans(
"RefDeliveryReceipt").
' : '.$object->ref;
331 $morehtmlref .=
'<br>'.$langs->trans(
'ThirdParty').
' : '.$expedition->thirdparty->getNomUrl(1);
333 if (!empty($conf->projet->enabled)) {
334 $langs->load(
"projects");
335 $morehtmlref .=
'<br>'.$langs->trans(
'Project').
' ';
337 if ($action !=
'classify') {
338 $morehtmlref .=
'<a class="editfielda" href="'.$_SERVER[
'PHP_SELF'].
'?action=classify&id='.$expedition->id.
'">'.
img_edit($langs->transnoentitiesnoconv(
'SetProject')).
'</a> : ';
340 if ($action ==
'classify') {
342 $morehtmlref .=
'<form method="post" action="'.$_SERVER[
'PHP_SELF'].
'?id='.$expedition->id.
'">';
343 $morehtmlref .=
'<input type="hidden" name="action" value="classin">';
344 $morehtmlref .=
'<input type="hidden" name="token" value="'.newToken().
'">';
345 $morehtmlref .= $formproject->select_projects($expedition->socid, $expedition->fk_project,
'projectid', $maxlength, 0, 1, 0, 1, 0, 0,
'', 1);
346 $morehtmlref .=
'<input type="submit" class="button" value="'.$langs->trans(
"Modify").
'">';
347 $morehtmlref .=
'</form>';
349 $morehtmlref .= $form->form_project(
$_SERVER[
'PHP_SELF'].
'?id='.$expedition->id, $expedition->socid, $expedition->fk_project,
'none', 0, 0, 0, 1);
352 $morehtmlref .=
' : ';
353 if (!empty($objectsrc->fk_project)) {
355 $proj->fetch($objectsrc->fk_project);
356 $morehtmlref .=
'<a href="'.DOL_URL_ROOT.
'/projet/card.php?id='.$objectsrc->fk_project.
'" title="'.$langs->trans(
'ShowProject').
'">';
357 $morehtmlref .= $proj->ref;
358 $morehtmlref .=
'</a>';
364 $morehtmlref .=
'</div>';
366 $morehtmlright = $langs->trans(
"StatusReceipt").
' : '.$object->getLibStatut(6).
'<br><br class="small">';
368 dol_banner_tab($expedition,
'ref', $linkback, 1,
'ref',
'ref', $morehtmlref,
'', 0,
'', $morehtmlright);
371 print '<div class="fichecenter">';
372 print '<div class="underbanner clearboth"></div>';
374 print '<table class="border tableforfield" width="100%">';
404 if ($typeobject ==
'commande' && $expedition->origin_id && !empty($conf->commande->enabled))
406 print '<tr><td class="titlefield">'.$langs->trans(
"RefOrder").
'</td>';
408 $order->fetch($expedition->origin_id);
409 print '<td colspan="3">';
410 print $order->getNomUrl(1,
'commande');
414 if ($typeobject ==
'propal' && $expedition->origin_id && !empty($conf->propal->enabled))
416 $propal =
new Propal($db);
417 $propal->fetch($expedition->origin_id);
418 print '<tr><td class="titlefield">'.$langs->trans(
"RefProposal").
'</td>';
419 print '<td colspan="3">';
420 print $propal->getNomUrl(1,
'expedition');
426 print '<tr><td class="titlefield">'.$langs->trans(
"DateCreation").
'</td>';
427 print '<td colspan="3">'.dol_print_date($object->date_creation,
'dayhour').
"</td>\n";
431 print '<tr><td height="10">';
432 print '<table class="nobordernopadding" width="100%"><tr><td>';
433 print $langs->trans(
'DateReceived');
436 if ($action !=
'editdate_delivery')
print '<td class="right"><a class="editfielda" href="'.$_SERVER[
"PHP_SELF"].
'?action=editdate_delivery&id='.$object->id.
'">'.
img_edit($langs->trans(
'SetDeliveryDate'), 1).
'</a></td>';
437 print '</tr></table>';
438 print
'</td><td colspan="2">';
439 if ($action ==
'editdate_delivery')
441 print
'<form name="setdate_delivery" action="'.$_SERVER[
"PHP_SELF"].
'?id='.$object->id.
'" method="post">';
442 print
'<input type="hidden" name="token" value="'.newToken().
'">';
443 print
'<input type="hidden" name="action" value="setdate_delivery">';
444 print $form->selectDate($object->date_delivery ? $object->date_delivery : -1,
'liv_', 1, 1,
'',
"setdate_delivery", 1, 1);
445 print
'<input type="submit" class="button" value="'.$langs->trans(
'Modify').
'">';
448 print $object->date_delivery ?
dol_print_date($object->date_delivery,
'dayhour') :
' ';
454 if (!empty($conf->incoterm->enabled))
457 print
'<table width="100%" class="nobordernopadding"><tr><td>';
458 print $langs->trans(
'IncotermLabel');
459 print
'<td><td class="right">';
460 if ($user->rights->expedition->delivery->creer) print
'<a class="editfielda" href="'.DOL_URL_ROOT.
'/delivery/card.php?id='.$object->id.
'&action=editincoterm">'.
img_edit().
'</a>';
462 print
'</td></tr></table>';
464 print
'<td colspan="3">';
465 if ($action !=
'editincoterm')
467 print $form->textwithpicto($object->display_incoterms(), $object->label_incoterms, 1);
469 print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms :
''), (!empty($object->location_incoterms) ? $object->location_incoterms :
''),
$_SERVER[
'PHP_SELF'].
'?id='.$object->id);
493 if (!$conf->expedition_bon->enabled && !empty($conf->stock->enabled))
497 $entrepot->fetch($object->entrepot_id);
498 print
'<tr><td width="20%">'.$langs->trans(
"Warehouse").
'</td>';
499 print
'<td colspan="3"><a href="'.DOL_URL_ROOT.
'/product/stock/card.php?id='.$entrepot->id.
'">'.$entrepot->label.
'</a></td>';
504 if ($action ==
'create_delivery') {
506 $extrafields->fetch_name_optionals_label($expedition->table_element);
507 if ($expedition->fetch_optionals() > 0) {
508 $object->array_options = array_merge($object->array_options, $expedition->array_options);
512 include DOL_DOCUMENT_ROOT.
'/core/tpl/extrafields_view.tpl.php';
514 print
"</table><br>\n";
522 $num_prod = count($object->lines);
525 print
'<table class="noborder centpercent">';
531 print
'<tr class="liste_titre">';
532 print
'<td>'.$langs->trans(
"Products").
'</td>';
533 print
'<td class="center">'.$langs->trans(
"QtyOrdered").
'</td>';
534 print
'<td class="center">'.$langs->trans(
"QtyReceived").
'</td>';
537 while ($i < $num_prod)
539 $parameters = array(
'i' => $i,
'line' => $object->lines[$i],
'num' => $num_prod);
540 $reshook = $hookmanager->executeHooks(
'printObjectLine', $parameters, $object, $action);
541 if ($reshook < 0)
setEventMessages($hookmanager->error, $hookmanager->errors,
'errors');
545 print
'<tr class="oddeven">';
546 if ($object->lines[$i]->fk_product > 0)
549 $product->fetch($object->lines[$i]->fk_product);
552 if (!empty($conf->global->MAIN_MULTILANGS) && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE))
554 $outputlangs = $langs;
556 if (empty($newlang) && !empty($_REQUEST[
'lang_id'])) $newlang = $_REQUEST[
'lang_id'];
557 if (empty($newlang)) $newlang = $object->thirdparty->default_lang;
558 if (!empty($newlang))
561 $outputlangs->setDefaultLang($newlang);
564 $label = (!empty($product->multilangs[$outputlangs->defaultlang][
"label"])) ? $product->multilangs[$outputlangs->defaultlang][
"label"] : $object->lines[$i]->product_label;
566 $label = (!empty($object->lines[$i]->label) ? $object->lines[$i]->label : $object->lines[$i]->product_label);
572 $text =
'<a href="'.DOL_URL_ROOT.
'/product/card.php?id='.$object->lines[$i]->fk_product.
'">';
573 if ($object->lines[$i]->fk_product_type == 1) $text .=
img_object($langs->trans(
'ShowService'),
'service');
574 else $text .=
img_object($langs->trans(
'ShowProduct'),
'product');
575 $text .=
' '.$object->lines[$i]->product_ref.
'</a>';
576 $text .=
' - '.$label;
577 $description = (!empty($conf->global->PRODUIT_DESC_IN_FORM) ?
'' :
dol_htmlentitiesbr($object->lines[$i]->description));
579 print $form->textwithtooltip($text, $description, 3,
'',
'', $i);
580 print_date_range($object->lines[$i]->date_start, $object->lines[$i]->date_end);
581 if (!empty($conf->global->PRODUIT_DESC_IN_FORM))
583 print (!empty($object->lines[$i]->description) && $object->lines[$i]->description != $object->lines[$i]->product_label) ?
'<br>'.dol_htmlentitiesbr($object->lines[$i]->description) :
'';
587 if ($object->lines[$i]->fk_product_type == 1) $text =
img_object($langs->trans(
'Service'),
'service');
588 else $text =
img_object($langs->trans(
'Product'),
'product');
590 if (!empty($object->lines[$i]->label)) {
591 $text .=
' <strong>'.$object->lines[$i]->label.
'</strong>';
592 print $form->textwithtooltip($text, $object->lines[$i]->description, 3,
'',
'', $i);
594 print $text.
' '.nl2br($object->lines[$i]->description);
601 print
'<td class="center">'.$object->lines[$i]->qty_asked.
'</td>';
602 print
'<td class="center">'.$object->lines[$i]->qty_shipped.
'</td>';
607 if (!empty($extrafields)) {
609 $mode = ($object->statut == 0) ?
'edit' :
'view';
611 $object->lines[$i]->fetch_optionals();
613 if ($action ==
'create_delivery') {
616 $extrafields->fetch_name_optionals_label($srcLine->table_element);
617 $srcLine->id = $expedition->lines[$i]->id;
618 $srcLine->fetch_optionals();
620 $object->lines[$i]->array_options = array_merge($object->lines[$i]->array_options, $srcLine->array_options);
622 print $object->lines[$i]->showOptionals($extrafields, $mode, array(
'style' =>
'class="oddeven"',
'colspan' => $colspan), $i);
643 if ($user->socid == 0)
645 print
'<div class="tabsAction">';
647 if ($object->statut == 0 && $num_prod > 0)
649 if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->expedition->delivery->creer))
650 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->expedition->delivery_advance->validate)))
652 print
'<a class="butAction" href="'.$_SERVER[
'PHP_SELF'].
'?id='.$object->id.
'&action=valid">'.$langs->trans(
"Validate").
'</a>';
656 if ($user->rights->expedition->delivery->supprimer)
658 if ($conf->expedition_bon->enabled)
660 print
'<a class="butActionDelete" href="'.$_SERVER[
'PHP_SELF'].
'?id='.$object->id.
'&expid='.$object->origin_id.
'&action=delete&token='.
newToken().
'&backtopage='.urlencode(DOL_URL_ROOT.
'/expedition/card.php?id='.$object->origin_id).
'">'.$langs->trans(
"Delete").
'</a>';
662 print
'<a class="butActionDelete" href="'.$_SERVER[
'PHP_SELF'].
'?id='.$object->id.
'&action=delete&token='.
newToken().
'">'.$langs->trans(
"Delete").
'</a>';
670 print
'<table width="100%" cellspacing="2"><tr><td width="50%" valign="top">';
677 $filedir = $conf->expedition->dir_output.
"/receipt/".$objectref;
678 $urlsource =
$_SERVER[
"PHP_SELF"].
"?id=".$object->id;
680 $genallowed = $user->rights->expedition->delivery->lire;
681 $delallowed = $user->rights->expedition->delivery->creer;
683 print $formfile->showdocuments(
'delivery', $objectref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0,
'',
'',
'', $soc->default_lang);
688 if ($object->origin ==
'expedition')
691 $shipment->fetch($object->origin_id);
695 $somethingshown = $form->showLinkedObjectBlock($object,
'');
699 print
'</td><td valign="top" width="50%">';
703 print
'</td></tr></table>';
706 print
"Expedition inexistante ou acces refuse";
710 print
"Expedition inexistante ou acces refuse";
Class to manage receptions.
GETPOST($paramname, $check= 'alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
img_edit($titlealt= 'default', $float=0, $other= '')
Show logo editer/modifier fiche.
Classe to manage lines of shipment.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm= 'auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
Class to manage products or services.
dol_now($mode= 'auto')
Return date for now.
dol_clone($object, $native=0)
Create a clone of instance of object (new instance with same value for properties) With native = 0: P...
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom= 'UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
delivery_prepare_head($object)
Prepare array with list of tabs.
setEventMessages($mesg, $mesgs, $style= 'mesgs', $messagekey= '')
Set event messages in dol_events session object.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage projects.
price2num($amount, $rounding= '', $option=0)
Function that return a number with universal decimal format (decimal separator is '...
Class to manage shipments.
Class to manage customers orders.
img_object($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
restrictedArea($user, $features, $objectid=0, $tableandshare= '', $feature2= '', $dbt_keyfield= 'fk_soc', $dbt_select= 'rowid', $isdraft=0)
Check permissions of a user to show a page and an object.
Class to manage translations.
dol_sanitizeFileName($str, $newstr= '_', $unaccent=1)
Clean a string to use it as a file name.
print $_SERVER["PHP_SELF"]
Edit parameters.
dol_get_fiche_head($links=array(), $active= '', $title= '', $notab=0, $picto= '', $pictoisfullpath=0, $morehtmlright= '', $morecss= '', $limittoshow=0, $moretabssuffix= '')
Show tabs of a record.
print
Draft customers invoices.
dol_print_date($time, $format= '', $tzoutput= 'auto', $outputlangs= '', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_print_error($db= '', $error= '', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
newToken()
Return the value of token currently saved into session with name 'newtoken'.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
print_date_range($date_start, $date_end, $format= '', $outputlangs= '')
Format output for start and end date.
dol_banner_tab($object, $paramid, $morehtml= '', $shownav=1, $fieldid= 'rowid', $fieldref= 'ref', $morehtmlref= '', $moreparam= '', $nodbprefix=0, $morehtmlleft= '', $morehtmlstatus= '', $onlybanner=0, $morehtmlright= '')
Show tab footer of a card.
Class to manage proposals.
Class to manage warehouses.