import java.text.DateFormat
import java.text.SimpleDateFormat
import javax.persistence.GeneratedValue
import ns org.osbp.mysmartshop.datatypes.Boolean
import ns org.osbp.mysmartshop.datatypes.Date
import ns org.osbp.mysmartshop.datatypes.PaymentMethod
import ns org.osbp.mysmartshop.datatypes.Price
import ns org.osbp.mysmartshop.datatypes.String
import ns org.osbp.mysmartshop.datatypes.Timestamp
import ns org.osbp.mysmartshop.datatypes.boolean
import ns org.osbp.mysmartshop.datatypes.double
import ns org.osbp.mysmartshop.datatypes.int
import ns org.osbp.mysmartshop.datatypes.long
  
/******************************************************************
 *                                                                *
 *  Copyright (C) - Loetz GmbH&Co.KG, 69115 Heidelberg, Germany
 *                                                                *
 *  This source was created by OSBP Softwarefactory Wizard!       *
 *                                                                *
 *  OSBP is (C) - Loetz GmbH&Co.KG, 69115 Heidelberg, Germany *
 *                                                                * 
 *================================================================*
 *                                                                *
 *  @file           $HeadURL$
 *  @version        $Revision$
 *  @date           $Date$
 *  @author         $Author$
 *                                                                *
 ******************************************************************/
package org.osbp.mysmartshop.entities {
 
	mappedSuperclass BaseID {
		id int id
		version long ^version
	}

	mappedSuperclass BaseUUID {
		uuid String id
		version long ^version
	}

	entity Bar extends BaseUUID {
		var String fooxxx
	}

	entity DtoTestParent extends BaseUUID {

		var String string

		ref cascade DtoTestChildContainment[ * ]containmentChilds opposite container

		ref DtoTestChildCrossRef[ * ]crossRefChilds opposite container
		ref DtoTestChildCrossRef crossRefChild

		var DtoTestBean beanx
	}

	entity DtoTestChildContainment extends BaseUUID {
		ref DtoTestParent container opposite containmentChilds
	}

	entity DtoTestChildCrossRef extends BaseUUID {
		ref DtoTestParent container opposite crossRefChilds
	}

	bean DtoTestBean {
		var String foo
		ref DtoTestChildCrossRef crossRefChild
	}

	entity Mcustomer extends BaseID {
		var long account_num
		var String lname
		var String fname
		var String mi
		var String address1
		var String address2
		var String address3
		var String address4
		var String city
		var String state_province
		var String postal_code
		var String country
		var String phone1
		var String phone2
		var Date birthdate
		var String marital_status
		var String yearly_income
		var String gender
		var int total_children
		var int num_children_at_home
		var String education
		var String date_accnt_opened
		var String member_card
		var String occupation
		var String houseowner
		var int num_cars_owned
		domainKey String fullname
		var String test
		ref CashSlip[ * ]slips opposite customer

		derived String foo {
			return country + "_" + city
		}

	}

	cacheable entity CashRegister extends BaseUUID {
		domainKey String num
		var String ip
		var String location
		var String currentDay
		ref CashSlip[ * ]slips opposite register

		unique index cashIpIndex {
			ip
		}

		unique index cashNumIndex {
			num
		}

	}

	entity CashSlip extends BaseUUID {
		var String currentDay
		var Timestamp now
		var String cashier
		var Price total
		@ javax.persistence.GeneratedValue var long serial
		var boolean payed
		ref cascade CashPosition[ * ]positions opposite slip
		ref Mcustomer customer opposite slips
		ref CashRegister register opposite slips
		ref cascade CashPayment[ * ]payments opposite slip
		def String when( ) {
			if( now != null ) {
				return java.text.SimpleDateFormat.getDateInstance( java.text.DateFormat.SHORT ).format( now )
			}
			return ""
		}

		index currentDay_index {
			currentDay
		}

		index serial_index {
			currentDay, serial
		}

	}

	entity CashPosition extends BaseUUID {
		ref CashSlip slip opposite positions

		var Timestamp now
		var double quantity
		var Price price
		var Price amount

		ref cascade CashSubPosition[ * ]subPositions opposite parent
	}

	entity CashSubPosition extends BaseUUID {
		var double quantity
		var Price price
		ref CashPosition parent opposite subPositions
	}

	entity CashPayment extends BaseUUID {
		var Timestamp now
		var Price payed
		ref CashSlip slip opposite payments
		ref CashPaymentMethod methodOfPayment opposite payments
		ref CashDrawerSum close opposite payments
	}

	entity CashPaymentMethod extends BaseUUID {
		domainKey String num
		domainDescription String name
		var Boolean credit
		var PaymentMethod imageName
		var double lowerLimit
		ref CashPayment[ * ]payments opposite methodOfPayment

		unique index paymentNumIndex {
			num
		}

	}

	/** relation of the company to the owner - not the user - of this personal information manager */
	entity CompanyRelationType extends BaseUUID {
	/** short name for this relation type */
		domainKey String name
		/** more detailed description */
		var String description
	}

	/** a company group consisting of a group of companies, from one is defined as the main company */
	entity CompanyGroup extends BaseUUID {
	/** name of the company group */
		domainKey String name
		/** more detailed description with usable information for the PIM owner */
		var String description
		/** the main company */
		ref Company main_company
		/** group of companies */
		ref Company[ * ]companies opposite company_group
	}

	/** a company */
	entity Company extends BaseUUID {
	/** the company group if any */
		ref CompanyGroup company_group opposite companies
		/** name of the company */
		domainKey String name
		/** more detailed description with usable information for the PIM owner */
		var String description
		/** relation of the company to the PIM owner */
		ref CompanyRelationType relation_type
		/** any number of addresses */
		ref cascade Address[ * ]address opposite company
		/** departments of this company */
		ref cascade Department[ * ]departments opposite company
	}

	/** an address */
	entity Address extends BaseUUID {
	/** if address for a company, the company is given */
		ref Company company opposite address
		/** if address for a department, the address is given */
		ref Department department opposite address
		/** if address for a person, the person is given */
		//        ref cascade PostalAddress[*] postal_adresses opposite address
		/** address field 1 */
		var String address1
		/** address field 2 */
		var String address2
		/** city */
		var String city
		/** state province */
		var String state_province
		/** postal code */
		var String postal_code
		/** country */
		var String country
		//        ref cascade Email[*] emails opposite address
		/** email */
		var String email
		//        ref cascade Phone[*] phones opposite address
		/** landline (Festnetznummer) */
		var String landline
		/** mobile */
		var String mobile
	}

	/** a companies department */
	entity Department extends BaseUUID {
	/** the company */
		ref Company company opposite departments
		/** name of the department */
		domainKey String name
		/** more detailed description with usable information for the PIM owner */
		var String description
		/** any number of addresses */
		ref cascade Address[ * ]address opposite department
		/** any number of employees */
		var double default_yearly_income
	}

	entity Test extends BaseUUID {

	}

	entity CashDrawerCurrency extends BaseUUID {

		ref cascade CashDrawerSum[ * ]sums opposite drawer
	}

	entity CashDrawerSum extends BaseUUID {

		ref CashDrawerCurrency drawer opposite sums
		ref cascade CashPayment[ * ] payments opposite close
	}

}